HHH-15604 Identically-named association in entity root and elementcollection of embeddables leads to assertion error
This commit is contained in:
parent
b774f80ce9
commit
2143ced49e
|
@ -1009,7 +1009,7 @@ public class ToOneAttributeMapping
|
|||
}
|
||||
return false;
|
||||
}
|
||||
else if ( parentNavigablePath.getParent() != null && creationState.resolveModelPart( parentNavigablePath.getParent() ) instanceof EmbeddedCollectionPart ) {//todo: handle recursively?
|
||||
else if ( isParentEmbeddedCollectionPart( creationState, parentNavigablePath.getParent() ) ) {
|
||||
/*
|
||||
class EntityA{
|
||||
@OneToOne(mappedBy = "identicallyNamedAssociation", fetch = FetchType.EAGER)
|
||||
|
@ -1081,6 +1081,22 @@ public class ToOneAttributeMapping
|
|||
return parentNavigablePath.isSuffix( bidirectionalAttributePath );
|
||||
}
|
||||
|
||||
private boolean isParentEmbeddedCollectionPart(DomainResultCreationState creationState, NavigablePath parentNavigablePath) {
|
||||
while ( parentNavigablePath != null ) {
|
||||
final ModelPart parentModelPart = creationState.resolveModelPart( parentNavigablePath );
|
||||
if ( parentModelPart instanceof EmbeddedCollectionPart ) {
|
||||
return true;
|
||||
}
|
||||
else if ( parentModelPart instanceof EmbeddableValuedModelPart ) {
|
||||
parentNavigablePath = parentNavigablePath.getParent();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Fetch createCircularBiDirectionalFetch(
|
||||
NavigablePath fetchablePath,
|
||||
FetchParent fetchParent,
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
package org.hibernate.orm.test.mapping.embeddable.elementcollection;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
EmbeddedElementCollectionWithIdenticallyNamedAssociation2Test.EntityA.class,
|
||||
EmbeddedElementCollectionWithIdenticallyNamedAssociation2Test.EntityB.class,
|
||||
}
|
||||
)
|
||||
@SessionFactory(
|
||||
statementInspectorClass = SQLStatementInspector.class
|
||||
)
|
||||
public class EmbeddedElementCollectionWithIdenticallyNamedAssociation2Test {
|
||||
|
||||
@BeforeAll
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
EntityA entityA1 = new EntityA( 1, "Fab" );
|
||||
EntityA entityA2 = new EntityA( 2, "And" );
|
||||
EntityB entityB = new EntityB( 1, "Chris" );
|
||||
|
||||
ElementCollectionHolder elementCollectionHolder = new ElementCollectionHolder();
|
||||
EmbeddableB embeddableB = new EmbeddableB( entityA2 );
|
||||
elementCollectionHolder.addElementCollection( embeddableB );
|
||||
entityB.setElementCollectionHolder( elementCollectionHolder );
|
||||
entityB.setNested( new IdenticallyNamedAssociationHolder( entityA1 ) );
|
||||
entityA1.setB( entityB );
|
||||
|
||||
session.persist( entityA1 );
|
||||
session.persist( entityA2 );
|
||||
session.persist( entityB );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet(SessionFactoryScope scope) {
|
||||
SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector();
|
||||
statementInspector.clear();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
EntityA entityA = session.get( EntityA.class, 1 );
|
||||
assertThat( entityA ).isNotNull();
|
||||
|
||||
EntityB entityB = entityA.getB();
|
||||
assertThat( entityB.getNested().getIdenticallyNamedAssociation() ).isEqualTo( entityA );
|
||||
|
||||
Set<EmbeddableB> elementCollection = entityB.getElementCollectionHolder().getElementCollection();
|
||||
assertThat( elementCollection.size() ).isEqualTo( 1 );
|
||||
|
||||
EmbeddableB embeddableB = elementCollection.iterator().next();
|
||||
EntityA identicallyNamedAssociation = embeddableB.getNested().getIdenticallyNamedAssociation();
|
||||
|
||||
assertThat( identicallyNamedAssociation ).isNotEqualTo( entityA );
|
||||
assertThat( identicallyNamedAssociation.getId()).isEqualTo( 2 );
|
||||
|
||||
assertThat( identicallyNamedAssociation.getB() ).isNull();
|
||||
|
||||
assertThat( statementInspector.getSqlQueries().size() ).isEqualTo( 2 );
|
||||
assertThat( statementInspector.getNumberOfJoins( 0 ) ).isEqualTo( 3 );
|
||||
assertThat( statementInspector.getNumberOfJoins( 1 ) ).isEqualTo( 4 );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Entity(name = "EntityA")
|
||||
public static class EntityA {
|
||||
@Id
|
||||
int id;
|
||||
|
||||
String name;
|
||||
|
||||
@OneToOne(mappedBy = "nested.identicallyNamedAssociation", fetch = FetchType.EAGER)
|
||||
EntityB b;
|
||||
|
||||
public EntityA() {
|
||||
}
|
||||
|
||||
public EntityA(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public EntityB getB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public void setB(EntityB b) {
|
||||
this.b = b;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "EntityB")
|
||||
public static class EntityB {
|
||||
@Id
|
||||
int id;
|
||||
|
||||
String name;
|
||||
|
||||
@Embedded
|
||||
IdenticallyNamedAssociationHolder nested;
|
||||
|
||||
@Embedded
|
||||
ElementCollectionHolder elementCollectionHolder;
|
||||
|
||||
public EntityB() {
|
||||
}
|
||||
|
||||
public EntityB(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ElementCollectionHolder getElementCollectionHolder() {
|
||||
return elementCollectionHolder;
|
||||
}
|
||||
|
||||
public void setElementCollectionHolder(ElementCollectionHolder elementCollectionHolder) {
|
||||
this.elementCollectionHolder = elementCollectionHolder;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public IdenticallyNamedAssociationHolder getNested() {
|
||||
return nested;
|
||||
}
|
||||
|
||||
public void setNested(IdenticallyNamedAssociationHolder nested) {
|
||||
this.nested = nested;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class IdenticallyNamedAssociationHolder {
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "entityA_id")
|
||||
EntityA identicallyNamedAssociation;
|
||||
|
||||
public IdenticallyNamedAssociationHolder() {
|
||||
}
|
||||
|
||||
public IdenticallyNamedAssociationHolder(EntityA identicallyNamedAssociation) {
|
||||
this.identicallyNamedAssociation = identicallyNamedAssociation;
|
||||
}
|
||||
|
||||
public EntityA getIdenticallyNamedAssociation() {
|
||||
return identicallyNamedAssociation;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class ElementCollectionHolder {
|
||||
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
Set<EmbeddableB> elementCollection = new HashSet<>();
|
||||
|
||||
public ElementCollectionHolder() {
|
||||
}
|
||||
|
||||
public Set<EmbeddableB> getElementCollection() {
|
||||
return elementCollection;
|
||||
}
|
||||
|
||||
public void setElementCollection(Set<EmbeddableB> elementCollection) {
|
||||
this.elementCollection = elementCollection;
|
||||
}
|
||||
|
||||
public void addElementCollection(EmbeddableB embeddableB) {
|
||||
this.elementCollection.add( embeddableB );
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class EmbeddableB {
|
||||
|
||||
@Embedded
|
||||
NestedEmbeddableB nested;
|
||||
|
||||
public EmbeddableB() {
|
||||
}
|
||||
|
||||
public EmbeddableB(EntityA identicallyNamedAssociation) {
|
||||
this.nested = new NestedEmbeddableB( identicallyNamedAssociation );
|
||||
}
|
||||
|
||||
public NestedEmbeddableB getNested() {
|
||||
return nested;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class NestedEmbeddableB {
|
||||
@OneToOne
|
||||
@JoinColumn(name = "entityA_id")
|
||||
EntityA identicallyNamedAssociation;
|
||||
|
||||
public NestedEmbeddableB() {
|
||||
}
|
||||
|
||||
public NestedEmbeddableB(EntityA identicallyNamedAssociation) {
|
||||
this.identicallyNamedAssociation = identicallyNamedAssociation;
|
||||
}
|
||||
|
||||
public EntityA getIdenticallyNamedAssociation() {
|
||||
return identicallyNamedAssociation;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue