From 7e4275c46ee5f24325285518e2a7297354bcea1b Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Mon, 16 Aug 2021 13:06:20 +0200 Subject: [PATCH] Loading circula bidirectional fetch associations not referring to PK --- .../internal/ToOneAttributeMapping.java | 2 +- .../CircularBiDirectionalFetchImpl.java | 68 +++++++++++++++---- .../{ => orm}/test/orphan/Mail.hbm.xml | 2 +- .../hibernate/{ => orm}/test/orphan/Mail.java | 2 +- .../test/orphan/PropertyRefTest.java | 6 +- .../{ => orm}/test/orphan/User.hbm.xml | 4 +- .../hibernate/{ => orm}/test/orphan/User.java | 16 ++--- 7 files changed, 70 insertions(+), 30 deletions(-) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/orphan/Mail.hbm.xml (93%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/orphan/Mail.java (95%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/orphan/PropertyRefTest.java (92%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/orphan/User.hbm.xml (84%) rename hibernate-core/src/test/java/org/hibernate/{ => orm}/test/orphan/User.java (78%) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index d684c106be..2b4e413a78 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -225,7 +225,7 @@ public class ToOneAttributeMapping if ( bidirectionalAttributeName == null ) { this.bidirectionalAttributeName = StringHelper.subStringNullIfEmpty( - bootValue.getReferencedPropertyName(), + referencedPropertyName, '.' ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java index f6b466e2c8..a6773cab55 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularBiDirectionalFetchImpl.java @@ -10,6 +10,7 @@ import org.hibernate.LockMode; import org.hibernate.engine.FetchTiming; import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.EntityKey; +import org.hibernate.engine.spi.EntityUniqueKey; import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.mapping.Association; @@ -18,8 +19,10 @@ import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.query.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.BiDirectionalFetch; @@ -43,7 +46,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor; public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Association { private final FetchTiming timing; private final NavigablePath navigablePath; - private final Fetchable fetchable; + private final ToOneAttributeMapping fetchable; private final FetchParent fetchParent; private final LockMode lockMode; @@ -53,7 +56,7 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc FetchTiming timing, NavigablePath navigablePath, FetchParent fetchParent, - Fetchable fetchable, + ToOneAttributeMapping fetchable, LockMode lockMode, NavigablePath referencedNavigablePath) { this.timing = timing; @@ -174,10 +177,10 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc private static class CircularFetchAssembler implements DomainResultAssembler { private final NavigablePath circularPath; private final JavaTypeDescriptor javaTypeDescriptor; - private final Fetchable fetchable; + private final ToOneAttributeMapping fetchable; public CircularFetchAssembler( - Fetchable fetchable, + ToOneAttributeMapping fetchable, NavigablePath circularPath, JavaTypeDescriptor javaTypeDescriptor) { this.fetchable = fetchable; @@ -196,22 +199,28 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc else { assert parentInitializer instanceof CollectionInitializer; final CollectionInitializer circ = (CollectionInitializer) parentInitializer; + final EntityPersister entityPersister = (EntityPersister) ( (AttributeMapping) fetchable ).getMappedType(); final CollectionKey collectionKey = circ.resolveCollectionKey( rowProcessingState ); - final EntityKey entityKey = new EntityKey( - collectionKey.getKey(), - (EntityPersister) ( (AttributeMapping) fetchable ).getMappedType() - ); + final Object key = collectionKey.getKey(); + final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState() .getSession(); final PersistenceContext persistenceContext = session.getPersistenceContext(); - final Object proxy = persistenceContext.getProxy( entityKey ); - // it is conceivable there is a proxy, so check that first - if ( proxy == null ) { - // otherwise look for an initialized version - return persistenceContext.getEntity( entityKey ); + if ( fetchable.getReferencedPropertyName() != null ) { + return loadByUniqueKey( entityPersister, key, session, persistenceContext ); + } + else { + final EntityKey entityKey = new EntityKey( key, entityPersister ); + + final Object proxy = persistenceContext.getProxy( entityKey ); + // it is conceivable there is a proxy, so check that first + if ( proxy == null ) { + // otherwise look for an initialized version + return persistenceContext.getEntity( entityKey ); + } + return proxy; } - return proxy; } } if ( initializer.getInitializedInstance() == null ) { @@ -221,6 +230,37 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc return initializer.getInitializedInstance(); } + private Object loadByUniqueKey( + EntityPersister entityPersister, + Object key, + SharedSessionContractImplementor session, + PersistenceContext persistenceContext) { + String uniqueKeyPropertyName = fetchable.getReferencedPropertyName(); + EntityUniqueKey euk = new EntityUniqueKey( + entityPersister.getEntityName(), + uniqueKeyPropertyName, + key, + entityPersister.getIdentifierType(), + entityPersister.getEntityMode(), + session.getFactory() + ); + Object entityInstance = persistenceContext.getEntity( euk ); + if ( entityInstance == null ) { + entityInstance = ( (UniqueKeyLoadable) entityPersister ).loadByUniqueKey( + uniqueKeyPropertyName, + key, + session + ); + + // If the entity was not in the Persistence Context, but was found now, + // add it to the Persistence Context + if ( entityInstance != null ) { + persistenceContext.addEntity( euk, entityInstance ); + } + } + return entityInstance; + } + private EntityInitializer resolveCircularInitializer(RowProcessingState rowProcessingState) { final Initializer initializer = rowProcessingState.resolveInitializer( circularPath ); if ( initializer instanceof EntityInitializer ) { diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/Mail.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/Mail.hbm.xml similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/test/orphan/Mail.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/orphan/Mail.hbm.xml index 1acb1d772a..ec09b3acb6 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/orphan/Mail.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/Mail.hbm.xml @@ -10,7 +10,7 @@ '-//Hibernate/Hibernate Mapping DTD 3.0//EN' 'http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd'> - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/Mail.java b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/Mail.java similarity index 95% rename from hibernate-core/src/test/java/org/hibernate/test/orphan/Mail.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/orphan/Mail.java index a2c10d01fd..f1ba88c914 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/orphan/Mail.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/Mail.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.orphan; +package org.hibernate.orm.test.orphan; public class Mail { diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/PropertyRefTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/PropertyRefTest.java similarity index 92% rename from hibernate-core/src/test/java/org/hibernate/test/orphan/PropertyRefTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/orphan/PropertyRefTest.java index 34da5331dc..a669f78239 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/orphan/PropertyRefTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/PropertyRefTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.orphan; +package org.hibernate.orm.test.orphan; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.orm.junit.DomainModel; @@ -20,8 +20,8 @@ import org.junit.jupiter.api.Test; @TestForIssue(jiraKey = "HHH-565") @DomainModel( xmlMappings = { - "org/hibernate/test/orphan/User.hbm.xml", - "org/hibernate/test/orphan/Mail.hbm.xml" + "org/hibernate/orm/test/orphan/User.hbm.xml", + "org/hibernate/orm/test/orphan/Mail.hbm.xml" } ) @SessionFactory diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/User.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/User.hbm.xml similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/test/orphan/User.hbm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/orphan/User.hbm.xml index 97ef4ee97e..e21d2cf4fa 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/orphan/User.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/User.hbm.xml @@ -10,7 +10,7 @@ '-//Hibernate/Hibernate Mapping DTD 3.0//EN' 'http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd'> - + @@ -22,7 +22,7 @@ - + diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/User.java b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/User.java similarity index 78% rename from hibernate-core/src/test/java/org/hibernate/test/orphan/User.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/orphan/User.java index 7b6639cf73..e01d60efda 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/orphan/User.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/orphan/User.java @@ -11,7 +11,7 @@ * Created on May 3, 2005, 9:42 AM */ -package org.hibernate.test.orphan; +package org.hibernate.orm.test.orphan; import java.util.HashSet; import java.util.Set; @@ -23,7 +23,7 @@ public class User { private Integer id; private String userid; - private Set mail = new HashSet(); + private Set mails = new HashSet(); public User() { } @@ -48,21 +48,21 @@ public class User { this.userid = userid; } - public Set getMail() { - return mail; + public Set getMails() { + return mails; } - private void setMail(Set mail) { - this.mail = mail; + private void setMails(Set mails) { + this.mails = mails; } public Mail addMail(String alias) { Mail mail = new Mail( alias, this ); - getMail().add( mail ); + getMails().add( mail ); return mail; } public void removeMail(Mail mail) { - getMail().remove( mail ); + getMails().remove( mail ); } }