mirror of
https://gitee.com/jmix/cuba.git
synced 2024-11-30 10:17:43 +08:00
Could not save Composition when master-entity is inheritted with the "joined" strategy #1013
This commit is contained in:
parent
7ebddfb683
commit
dfec903dc1
@ -452,6 +452,13 @@ configure(coreModule) {
|
||||
]
|
||||
}
|
||||
|
||||
task testJoinedComposition(type: Test) {
|
||||
scanForTestClasses = false
|
||||
includes = ['spec/cuba/core/composition/joined_composition/JoinedCompositionTestClass.class']
|
||||
}
|
||||
|
||||
test.finalizedBy testJoinedComposition
|
||||
|
||||
assembleDbScripts {
|
||||
moduleAlias = '10-cuba'
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package com.haulmont.cuba.core.sys.persistence;
|
||||
import com.google.common.base.Strings;
|
||||
import com.haulmont.chile.core.model.MetaClass;
|
||||
import com.haulmont.chile.core.model.MetaProperty;
|
||||
import com.haulmont.chile.core.model.Range;
|
||||
import com.haulmont.cuba.core.entity.Entity;
|
||||
import com.haulmont.cuba.core.entity.SoftDelete;
|
||||
import com.haulmont.cuba.core.entity.annotation.EmbeddedParameters;
|
||||
@ -31,21 +32,16 @@ import com.haulmont.cuba.core.sys.UuidConverter;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.eclipse.persistence.annotations.CacheCoordinationType;
|
||||
import org.eclipse.persistence.config.CacheIsolationType;
|
||||
import org.eclipse.persistence.descriptors.ClassDescriptor;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEventListener;
|
||||
import org.eclipse.persistence.descriptors.DescriptorEventManager;
|
||||
import org.eclipse.persistence.descriptors.*;
|
||||
import org.eclipse.persistence.expressions.ExpressionBuilder;
|
||||
import org.eclipse.persistence.internal.helper.DatabaseField;
|
||||
import org.eclipse.persistence.mappings.*;
|
||||
import org.eclipse.persistence.platform.database.PostgreSQLPlatform;
|
||||
import org.eclipse.persistence.queries.ReadQuery;
|
||||
import org.eclipse.persistence.sessions.Session;
|
||||
import org.eclipse.persistence.sessions.SessionEvent;
|
||||
import org.eclipse.persistence.sessions.SessionEventAdapter;
|
||||
|
||||
import javax.persistence.OneToOne;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.sql.Types;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -64,13 +60,17 @@ public class EclipseLinkSessionEventListener extends SessionEventAdapter {
|
||||
setPrintInnerJoinOnClause(session);
|
||||
|
||||
Map<Class, ClassDescriptor> descriptorMap = session.getDescriptors();
|
||||
|
||||
boolean hasMultipleTableConstraintDependency = hasMultipleTableConstraintDependency();
|
||||
for (Map.Entry<Class, ClassDescriptor> entry : descriptorMap.entrySet()) {
|
||||
MetaClass metaClass = metadata.getSession().getClassNN(entry.getKey());
|
||||
ClassDescriptor desc = entry.getValue();
|
||||
|
||||
setCacheable(metaClass, desc, session);
|
||||
|
||||
if (hasMultipleTableConstraintDependency) {
|
||||
setMultipleTableConstraintDependency(metaClass, desc);
|
||||
}
|
||||
|
||||
if (Entity.class.isAssignableFrom(desc.getJavaClass())) {
|
||||
// set DescriptorEventManager that doesn't invoke listeners for base classes
|
||||
desc.setEventManager(new DescriptorEventManager() {
|
||||
@ -165,6 +165,24 @@ public class EclipseLinkSessionEventListener extends SessionEventAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private void setMultipleTableConstraintDependency(MetaClass metaClass, ClassDescriptor desc) {
|
||||
InheritancePolicy policy = desc.getInheritancePolicyOrNull();
|
||||
if (policy != null && policy.isJoinedStrategy() && policy.getParentClass() != null) {
|
||||
boolean hasOneToMany = metaClass.getOwnProperties().stream().anyMatch(metaProperty ->
|
||||
metadata.getTools().isPersistent(metaProperty)
|
||||
&& metaProperty.getRange().isClass()
|
||||
&& metaProperty.getRange().getCardinality() == Range.Cardinality.ONE_TO_MANY);
|
||||
if (hasOneToMany) {
|
||||
desc.setHasMultipleTableConstraintDependecy(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasMultipleTableConstraintDependency() {
|
||||
return BooleanUtils.toBoolean(
|
||||
AppContext.getProperty("cuba.hasMultipleTableConstraintDependency"));
|
||||
}
|
||||
|
||||
private void setDatabaseFieldParameters(Session session, DatabaseField field) {
|
||||
if (session.getPlatform() instanceof PostgreSQLPlatform) {
|
||||
field.setSqlType(Types.OTHER);
|
||||
|
@ -128,6 +128,21 @@ create table TEST_ROOT_ENTITY_DETAIL (
|
||||
primary key (ID)
|
||||
)^
|
||||
|
||||
|
||||
create table TEST_CHILD_ENTITY_DETAIL (
|
||||
ID varchar(36) not null,
|
||||
CREATE_TS timestamp,
|
||||
CREATED_BY varchar(50),
|
||||
VERSION integer,
|
||||
UPDATE_TS timestamp,
|
||||
UPDATED_BY varchar(50),
|
||||
DELETE_TS timestamp,
|
||||
DELETED_BY varchar(50),
|
||||
INFO varchar(255),
|
||||
CHILD_ENTITY_ID varchar(36) not null,
|
||||
constraint TEST_CHILD_ENTITY_DETAIL_CHILD_ENTITY foreign key (CHILD_ENTITY_ID) references TEST_CHILD_ENTITY(ENTITY_ID),
|
||||
primary key (ID)
|
||||
)^
|
||||
------------------------------------------------------------------------------------------------------------
|
||||
|
||||
create table TEST_SOFT_DELETE_OTO_B (
|
||||
|
@ -16,7 +16,10 @@
|
||||
|
||||
package com.haulmont.cuba.testmodel.selfinherited;
|
||||
|
||||
import com.haulmont.chile.core.annotations.Composition;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
@DiscriminatorValue("C")
|
||||
@Entity(name = "test$ChildEntity")
|
||||
@ -28,6 +31,10 @@ public class ChildEntity extends RootEntity {
|
||||
@Column(name = "NAME")
|
||||
protected String name;
|
||||
|
||||
@OneToMany(mappedBy = "childEntity")
|
||||
@Composition
|
||||
protected List<ChildEntityDetail> childDetails;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2018 Haulmont.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.testmodel.selfinherited;
|
||||
|
||||
import com.haulmont.cuba.core.entity.StandardEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Table(name = "TEST_CHILD_ENTITY_DETAIL")
|
||||
@Entity(name = "test$ChildEntityDetail")
|
||||
public class ChildEntityDetail extends StandardEntity {
|
||||
|
||||
private static final long serialVersionUID = -3794606860555343620L;
|
||||
|
||||
@Column(name = "INFO")
|
||||
protected String info;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "CHILD_ENTITY_ID")
|
||||
protected ChildEntity childEntity;
|
||||
|
||||
public String getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public void setInfo(String info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public ChildEntity getChildEntity() {
|
||||
return childEntity;
|
||||
}
|
||||
|
||||
public void setChildEntity(ChildEntity childEntity) {
|
||||
this.childEntity = childEntity;
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
<class>com.haulmont.cuba.testmodel.selfinherited.RootEntity</class>
|
||||
<class>com.haulmont.cuba.testmodel.selfinherited.ChildEntity</class>
|
||||
<class>com.haulmont.cuba.testmodel.selfinherited.RootEntityDetail</class>
|
||||
<class>com.haulmont.cuba.testmodel.selfinherited.ChildEntityDetail</class>
|
||||
<class>com.haulmont.cuba.testmodel.softdelete_one_to_one.SoftDeleteOneToOneA</class>
|
||||
<class>com.haulmont.cuba.testmodel.softdelete_one_to_one.SoftDeleteOneToOneB</class>
|
||||
<class>com.haulmont.cuba.testmodel.cascadedelete.CascadeEntity</class>
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2018 Haulmont.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package spec.cuba.core.composition.joined_composition
|
||||
|
||||
import com.haulmont.bali.db.QueryRunner
|
||||
import com.haulmont.cuba.core.Persistence
|
||||
import com.haulmont.cuba.core.global.AppBeans
|
||||
import com.haulmont.cuba.core.global.DataManager
|
||||
import com.haulmont.cuba.core.global.Metadata
|
||||
import com.haulmont.cuba.testmodel.selfinherited.ChildEntity
|
||||
import com.haulmont.cuba.testmodel.selfinherited.ChildEntityDetail
|
||||
import com.haulmont.cuba.testsupport.TestContainer
|
||||
import org.junit.ClassRule
|
||||
import spock.lang.Shared
|
||||
import spock.lang.Specification
|
||||
|
||||
class JoinedCompositionTestClass extends Specification {
|
||||
|
||||
@Shared
|
||||
@ClassRule
|
||||
public TestContainer cont = new TestContainer()
|
||||
.setAppPropertiesFiles(Arrays.asList("cuba-app.properties", "test-app.properties", "cuba-test-app.properties", "/spec/cuba/core/composition/test-composition-app.properties"))
|
||||
|
||||
private Persistence persistence = cont.persistence()
|
||||
private Metadata metadata = cont.metadata()
|
||||
|
||||
private dataManager
|
||||
|
||||
void setup() {
|
||||
dataManager = AppBeans.get(DataManager)
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
def runner = new QueryRunner(persistence.dataSource)
|
||||
runner.update('delete from TEST_CHILD_ENTITY_DETAIL')
|
||||
runner.update('delete from TEST_ROOT_ENTITY_DETAIL')
|
||||
runner.update('delete from TEST_CHILD_ENTITY')
|
||||
runner.update('delete from TEST_ROOT_ENTITY')
|
||||
}
|
||||
|
||||
def "store master-detail"() {
|
||||
when:
|
||||
persistence.runInTransaction({ em ->
|
||||
ChildEntity childEntity = metadata.create(ChildEntity)
|
||||
childEntity.name = 'name'
|
||||
childEntity.description = 'description'
|
||||
em.persist(childEntity)
|
||||
|
||||
ChildEntityDetail childEntityDetail = metadata.create(ChildEntityDetail)
|
||||
childEntityDetail.childEntity = childEntity
|
||||
childEntityDetail.info = 'info'
|
||||
em.persist(childEntityDetail)
|
||||
})
|
||||
|
||||
then:
|
||||
noExceptionThrown()
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2008-2018 Haulmont.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# This file contains properties needed only for testing inside CUBA.
|
||||
# Do not include it to test properties of your project.
|
||||
|
||||
cuba.hasMultipleTableConstraintDependency = true
|
Loading…
Reference in New Issue
Block a user