Fix ToOneAttributeMapping bidirectionalAttributeName value determination
This commit is contained in:
parent
71204a9e97
commit
7dc70e9350
|
@ -31,6 +31,7 @@ import org.hibernate.mapping.PersistentClass;
|
|||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metamodel.mapping.AssociationKey;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
|
@ -236,7 +237,10 @@ public class ToOneAttributeMapping
|
|||
final Iterator<Property> propertyClosureIterator = entityBinding.getPropertyClosureIterator();
|
||||
while ( propertyClosureIterator.hasNext() ) {
|
||||
final Property property = propertyClosureIterator.next();
|
||||
if ( property.getValue() instanceof OneToOne && name.equals( ( (OneToOne) property.getValue() ).getMappedByProperty() ) ) {
|
||||
if ( property.getValue() instanceof OneToOne
|
||||
&& name.equals( ( (OneToOne) property.getValue() ).getMappedByProperty() )
|
||||
&& ( (OneToOne) property.getValue() ).getReferencedEntityName().equals(
|
||||
declaringType.getJavaTypeDescriptor().getJavaType().getTypeName() ) ) {
|
||||
bidirectionalAttributeName = property.getName();
|
||||
break;
|
||||
}
|
||||
|
@ -247,7 +251,11 @@ public class ToOneAttributeMapping
|
|||
final Iterator<Property> propertyClosureIterator = entityBinding.getPropertyClosureIterator();
|
||||
while ( propertyClosureIterator.hasNext() ) {
|
||||
final Property property = propertyClosureIterator.next();
|
||||
if ( property.getValue() instanceof Collection && name.equals( ( (Collection) property.getValue() ).getMappedByProperty() ) ) {
|
||||
final Value value = property.getValue();
|
||||
if ( value instanceof Collection
|
||||
&& name.equals( ( (Collection) value ).getMappedByProperty() )
|
||||
&& ( (Collection) value ).getElement().getType().getName()
|
||||
.equals( declaringType.getJavaTypeDescriptor().getJavaType().getTypeName() ) ) {
|
||||
bidirectionalAttributeName = property.getName();
|
||||
break;
|
||||
}
|
||||
|
@ -1046,6 +1054,7 @@ public class ToOneAttributeMapping
|
|||
final ModelPart bidirectionalModelPart = entityMappingType.findSubPart( bidirectionalAttributeName );
|
||||
// Add the inverse association key side as well to be able to resolve to a CircularFetch
|
||||
if ( bidirectionalModelPart instanceof ToOneAttributeMapping ) {
|
||||
assert bidirectionalModelPart.getPartMappingType() == declaringTableGroupProducer;
|
||||
final ToOneAttributeMapping bidirectionalAttribute = (ToOneAttributeMapping) bidirectionalModelPart;
|
||||
final AssociationKey secondKey = bidirectionalAttribute.getForeignKeyDescriptor().getAssociationKey();
|
||||
if ( creationState.registerVisitedAssociationKey( secondKey ) ) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.PropertyAccessException;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.property.access.internal.AbstractFieldSerialForm;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
||||
/**
|
||||
* Field-based implementation of Setter
|
||||
|
@ -67,15 +68,19 @@ public class SetterFieldImpl implements Setter {
|
|||
);
|
||||
}
|
||||
else {
|
||||
final String valueType;
|
||||
if ( value instanceof HibernateProxy ) {
|
||||
valueType = ( (HibernateProxy) value ).getHibernateLazyInitializer().getEntityName();
|
||||
}
|
||||
else {
|
||||
valueType = value.getClass().getTypeName();
|
||||
}
|
||||
throw new PropertyAccessException(
|
||||
e,
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"Could not set value [%s (`%s`)] by reflection",
|
||||
value,
|
||||
value == null ? "<null>" : value.getClass().getTypeName(),
|
||||
containerClass == null ? "<dynamic>" : containerClass.getTypeName(),
|
||||
propertyName
|
||||
"Could not set value of type [%s]",
|
||||
valueType
|
||||
),
|
||||
true,
|
||||
containerClass,
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.mapping.AssociationKey;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
|
@ -50,9 +49,7 @@ public interface DomainResultCreationState {
|
|||
* Resolve the ModelPart associated with a given NavigablePath. More specific ModelParts should be preferred - e.g.
|
||||
* the SingularAssociationAttributeMapping rather than just the EntityTypeMapping for the associated type
|
||||
*/
|
||||
default ModelPart resolveModelPart(NavigablePath navigablePath) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
ModelPart resolveModelPart(NavigablePath navigablePath);
|
||||
|
||||
/**
|
||||
* Visit fetches for the given parent.
|
||||
|
|
|
@ -6,8 +6,11 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.loading;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
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.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
|
@ -15,16 +18,19 @@ import jakarta.persistence.OneToOne;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class LoadContainedInDoubleContainingTest extends BaseCoreFunctionalTestCase {
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
LoadContainedInDoubleContainingTest.Containing.class,
|
||||
LoadContainedInDoubleContainingTest.OtherContained.class,
|
||||
LoadContainedInDoubleContainingTest.Contained.class
|
||||
}
|
||||
)
|
||||
@SessionFactory
|
||||
public class LoadContainedInDoubleContainingTest {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Containing.class, OtherContained.class, Contained.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
inTransaction( session -> {
|
||||
@BeforeEach
|
||||
public void setUp(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
Containing containing = new Containing( 1, "initial" );
|
||||
OtherContained otherContained = new OtherContained( 2, "initial" );
|
||||
containing.setOtherContained( otherContained );
|
||||
|
@ -32,19 +38,20 @@ public class LoadContainedInDoubleContainingTest extends BaseCoreFunctionalTestC
|
|||
session.persist( containing );
|
||||
session.persist( otherContained );
|
||||
} );
|
||||
}
|
||||
|
||||
inTransaction( session -> {
|
||||
OtherContained entity = session.load( OtherContained.class, 2 );
|
||||
String text = entity.getText();
|
||||
@Test
|
||||
public void test(SessionFactoryScope scope) {
|
||||
scope.inTransaction( session -> {
|
||||
OtherContained otherContained = session.load( OtherContained.class, 2 );
|
||||
String text = otherContained.getText();
|
||||
assertThat( text ).isEqualTo( "initial" );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = Containing.NAME)
|
||||
@Entity(name = "Containing")
|
||||
public static class Containing {
|
||||
|
||||
static final String NAME = "Containing";
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
private String text;
|
||||
|
@ -69,34 +76,39 @@ public class LoadContainedInDoubleContainingTest extends BaseCoreFunctionalTestC
|
|||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Contained getContained() {
|
||||
return contained;
|
||||
}
|
||||
|
||||
public void setContained(Contained contained) {
|
||||
this.contained = contained;
|
||||
}
|
||||
|
||||
public OtherContained getOtherContained() {
|
||||
return otherContained;
|
||||
}
|
||||
|
||||
public void setOtherContained(OtherContained otherContained) {
|
||||
this.otherContained = otherContained;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = Contained.NAME)
|
||||
@Entity(name = "Contained")
|
||||
public static class Contained {
|
||||
|
||||
static final String NAME = "Contained";
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
private String text;
|
||||
|
@ -115,28 +127,31 @@ public class LoadContainedInDoubleContainingTest extends BaseCoreFunctionalTestC
|
|||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Containing getContaining() {
|
||||
return containing;
|
||||
}
|
||||
|
||||
public void setContaining(Containing containing) {
|
||||
this.containing = containing;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = OtherContained.NAME)
|
||||
@Entity(name = "OtherContained")
|
||||
public static class OtherContained {
|
||||
|
||||
static final String NAME = "OtherContained";
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
private String text;
|
||||
|
@ -155,18 +170,23 @@ public class LoadContainedInDoubleContainingTest extends BaseCoreFunctionalTestC
|
|||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Containing getContaining() {
|
||||
return containing;
|
||||
}
|
||||
|
||||
public void setContaining(Containing containing) {
|
||||
this.containing = containing;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue