Loading circula bidirectional fetch associations not referring to PK

This commit is contained in:
Andrea Boriero 2021-08-16 13:06:20 +02:00 committed by Andrea Boriero
parent 053153847b
commit 7e4275c46e
7 changed files with 70 additions and 30 deletions

View File

@ -225,7 +225,7 @@ public class ToOneAttributeMapping
if ( bidirectionalAttributeName == null ) {
this.bidirectionalAttributeName = StringHelper.subStringNullIfEmpty(
bootValue.getReferencedPropertyName(),
referencedPropertyName,
'.'
);
}

View File

@ -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,15 +199,20 @@ 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();
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 ) {
@ -214,6 +222,7 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc
return proxy;
}
}
}
if ( initializer.getInitializedInstance() == null ) {
initializer.resolveKey( rowProcessingState );
initializer.resolveInstance( rowProcessingState );
@ -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 ) {

View File

@ -10,7 +10,7 @@
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
'http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd'>
<hibernate-mapping package="org.hibernate.test.orphan" >
<hibernate-mapping package="org.hibernate.orm.test.orphan" >
<class name="Mail" table="t_mail">

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.orphan;
package org.hibernate.orm.test.orphan;
public class Mail {

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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

View File

@ -10,7 +10,7 @@
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
'http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd'>
<hibernate-mapping package="org.hibernate.test.orphan" >
<hibernate-mapping package="org.hibernate.orm.test.orphan" >
<class name="User" table="t_user">
@ -22,7 +22,7 @@
<column name="userid" length="32" not-null="true"/>
</property>
<set name="mail" table="mail" cascade="all, delete-orphan" inverse="true" lazy="false">
<set name="mails" table="mail" cascade="all, delete-orphan" inverse="true" lazy="false">
<key column="userid" property-ref="userid" not-null="false"/>
<one-to-many class="Mail"/>
</set>

View File

@ -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> mail = new HashSet();
private Set<Mail> mails = new HashSet();
public User() {
}
@ -48,21 +48,21 @@ public class User {
this.userid = userid;
}
public Set<Mail> getMail() {
return mail;
public Set<Mail> getMails() {
return mails;
}
private void setMail(Set<Mail> mail) {
this.mail = mail;
private void setMails(Set<Mail> 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 );
}
}