Loading circula bidirectional fetch associations not referring to PK
This commit is contained in:
parent
053153847b
commit
7e4275c46e
|
@ -225,7 +225,7 @@ public class ToOneAttributeMapping
|
|||
|
||||
if ( bidirectionalAttributeName == null ) {
|
||||
this.bidirectionalAttributeName = StringHelper.subStringNullIfEmpty(
|
||||
bootValue.getReferencedPropertyName(),
|
||||
referencedPropertyName,
|
||||
'.'
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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">
|
||||
|
|
@ -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 {
|
|
@ -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
|
|
@ -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>
|
|
@ -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 );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue