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 ) {
|
if ( bidirectionalAttributeName == null ) {
|
||||||
this.bidirectionalAttributeName = StringHelper.subStringNullIfEmpty(
|
this.bidirectionalAttributeName = StringHelper.subStringNullIfEmpty(
|
||||||
bootValue.getReferencedPropertyName(),
|
referencedPropertyName,
|
||||||
'.'
|
'.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.CollectionKey;
|
import org.hibernate.engine.spi.CollectionKey;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
|
import org.hibernate.engine.spi.EntityUniqueKey;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.metamodel.mapping.Association;
|
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.ForeignKeyDescriptor;
|
||||||
import org.hibernate.metamodel.mapping.MappingType;
|
import org.hibernate.metamodel.mapping.MappingType;
|
||||||
import org.hibernate.metamodel.mapping.ModelPart;
|
import org.hibernate.metamodel.mapping.ModelPart;
|
||||||
|
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.UniqueKeyLoadable;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||||
import org.hibernate.sql.results.graph.BiDirectionalFetch;
|
import org.hibernate.sql.results.graph.BiDirectionalFetch;
|
||||||
|
@ -43,7 +46,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||||
public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Association {
|
public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Association {
|
||||||
private final FetchTiming timing;
|
private final FetchTiming timing;
|
||||||
private final NavigablePath navigablePath;
|
private final NavigablePath navigablePath;
|
||||||
private final Fetchable fetchable;
|
private final ToOneAttributeMapping fetchable;
|
||||||
|
|
||||||
private final FetchParent fetchParent;
|
private final FetchParent fetchParent;
|
||||||
private final LockMode lockMode;
|
private final LockMode lockMode;
|
||||||
|
@ -53,7 +56,7 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc
|
||||||
FetchTiming timing,
|
FetchTiming timing,
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
FetchParent fetchParent,
|
FetchParent fetchParent,
|
||||||
Fetchable fetchable,
|
ToOneAttributeMapping fetchable,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
NavigablePath referencedNavigablePath) {
|
NavigablePath referencedNavigablePath) {
|
||||||
this.timing = timing;
|
this.timing = timing;
|
||||||
|
@ -174,10 +177,10 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc
|
||||||
private static class CircularFetchAssembler implements DomainResultAssembler {
|
private static class CircularFetchAssembler implements DomainResultAssembler {
|
||||||
private final NavigablePath circularPath;
|
private final NavigablePath circularPath;
|
||||||
private final JavaTypeDescriptor javaTypeDescriptor;
|
private final JavaTypeDescriptor javaTypeDescriptor;
|
||||||
private final Fetchable fetchable;
|
private final ToOneAttributeMapping fetchable;
|
||||||
|
|
||||||
public CircularFetchAssembler(
|
public CircularFetchAssembler(
|
||||||
Fetchable fetchable,
|
ToOneAttributeMapping fetchable,
|
||||||
NavigablePath circularPath,
|
NavigablePath circularPath,
|
||||||
JavaTypeDescriptor javaTypeDescriptor) {
|
JavaTypeDescriptor javaTypeDescriptor) {
|
||||||
this.fetchable = fetchable;
|
this.fetchable = fetchable;
|
||||||
|
@ -196,22 +199,28 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc
|
||||||
else {
|
else {
|
||||||
assert parentInitializer instanceof CollectionInitializer;
|
assert parentInitializer instanceof CollectionInitializer;
|
||||||
final CollectionInitializer circ = (CollectionInitializer) parentInitializer;
|
final CollectionInitializer circ = (CollectionInitializer) parentInitializer;
|
||||||
|
final EntityPersister entityPersister = (EntityPersister) ( (AttributeMapping) fetchable ).getMappedType();
|
||||||
final CollectionKey collectionKey = circ.resolveCollectionKey( rowProcessingState );
|
final CollectionKey collectionKey = circ.resolveCollectionKey( rowProcessingState );
|
||||||
final EntityKey entityKey = new EntityKey(
|
final Object key = collectionKey.getKey();
|
||||||
collectionKey.getKey(),
|
|
||||||
(EntityPersister) ( (AttributeMapping) fetchable ).getMappedType()
|
|
||||||
);
|
|
||||||
|
|
||||||
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState()
|
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState()
|
||||||
.getSession();
|
.getSession();
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||||
final Object proxy = persistenceContext.getProxy( entityKey );
|
if ( fetchable.getReferencedPropertyName() != null ) {
|
||||||
// it is conceivable there is a proxy, so check that first
|
return loadByUniqueKey( entityPersister, key, session, persistenceContext );
|
||||||
if ( proxy == null ) {
|
}
|
||||||
// otherwise look for an initialized version
|
else {
|
||||||
return persistenceContext.getEntity( entityKey );
|
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 ) {
|
if ( initializer.getInitializedInstance() == null ) {
|
||||||
|
@ -221,6 +230,37 @@ public class CircularBiDirectionalFetchImpl implements BiDirectionalFetch, Assoc
|
||||||
return initializer.getInitializedInstance();
|
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) {
|
private EntityInitializer resolveCircularInitializer(RowProcessingState rowProcessingState) {
|
||||||
final Initializer initializer = rowProcessingState.resolveInitializer( circularPath );
|
final Initializer initializer = rowProcessingState.resolveInitializer( circularPath );
|
||||||
if ( initializer instanceof EntityInitializer ) {
|
if ( initializer instanceof EntityInitializer ) {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
|
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
|
||||||
'http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd'>
|
'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">
|
<class name="Mail" table="t_mail">
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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 {
|
public class Mail {
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* 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.TestForIssue;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
@ -20,8 +20,8 @@ import org.junit.jupiter.api.Test;
|
||||||
@TestForIssue(jiraKey = "HHH-565")
|
@TestForIssue(jiraKey = "HHH-565")
|
||||||
@DomainModel(
|
@DomainModel(
|
||||||
xmlMappings = {
|
xmlMappings = {
|
||||||
"org/hibernate/test/orphan/User.hbm.xml",
|
"org/hibernate/orm/test/orphan/User.hbm.xml",
|
||||||
"org/hibernate/test/orphan/Mail.hbm.xml"
|
"org/hibernate/orm/test/orphan/Mail.hbm.xml"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@SessionFactory
|
@SessionFactory
|
|
@ -10,7 +10,7 @@
|
||||||
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
|
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
|
||||||
'http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd'>
|
'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">
|
<class name="User" table="t_user">
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<column name="userid" length="32" not-null="true"/>
|
<column name="userid" length="32" not-null="true"/>
|
||||||
</property>
|
</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"/>
|
<key column="userid" property-ref="userid" not-null="false"/>
|
||||||
<one-to-many class="Mail"/>
|
<one-to-many class="Mail"/>
|
||||||
</set>
|
</set>
|
|
@ -11,7 +11,7 @@
|
||||||
* Created on May 3, 2005, 9:42 AM
|
* 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.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public class User {
|
||||||
|
|
||||||
private Integer id;
|
private Integer id;
|
||||||
private String userid;
|
private String userid;
|
||||||
private Set<Mail> mail = new HashSet();
|
private Set<Mail> mails = new HashSet();
|
||||||
|
|
||||||
public User() {
|
public User() {
|
||||||
}
|
}
|
||||||
|
@ -48,21 +48,21 @@ public class User {
|
||||||
this.userid = userid;
|
this.userid = userid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Mail> getMail() {
|
public Set<Mail> getMails() {
|
||||||
return mail;
|
return mails;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMail(Set<Mail> mail) {
|
private void setMails(Set<Mail> mails) {
|
||||||
this.mail = mail;
|
this.mails = mails;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mail addMail(String alias) {
|
public Mail addMail(String alias) {
|
||||||
Mail mail = new Mail( alias, this );
|
Mail mail = new Mail( alias, this );
|
||||||
getMail().add( mail );
|
getMails().add( mail );
|
||||||
return mail;
|
return mail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeMail(Mail mail) {
|
public void removeMail(Mail mail) {
|
||||||
getMail().remove( mail );
|
getMails().remove( mail );
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue