Fix create a new instance while a corresponding one is loading

This commit is contained in:
Andrea Boriero 2021-07-09 21:01:14 +02:00
parent 8dcd63dcee
commit 96f8273673
6 changed files with 81 additions and 59 deletions

View File

@ -480,7 +480,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
else { else {
// look to see if another initializer from a parent load context or an earlier // look to see if another initializer from a parent load context or an earlier
// initializer is already loading the entity // initializer is already loading the entity
if ( entityInstance == null ) {
entityInstance = resolveInstance( entityInstance = resolveInstance(
entityIdentifier, entityIdentifier,
rowProcessingState, rowProcessingState,
@ -489,7 +488,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
); );
} }
}
if ( LockMode.NONE != lockMode ) { if ( LockMode.NONE != lockMode ) {
final EntityEntry entry = session.getPersistenceContextInternal().getEntry( entityInstance ); final EntityEntry entry = session.getPersistenceContextInternal().getEntry( entityInstance );
@ -646,13 +644,16 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
if ( !hibernateLazyInitializer.isUninitialized() ) { if ( !hibernateLazyInitializer.isUninitialized() ) {
return; return;
} }
Object instance = resolveInstance( Object instance = persistenceContext.getEntity( entityKey );
if ( instance == null ) {
instance = resolveInstance(
entityKey.getIdentifier(), entityKey.getIdentifier(),
rowProcessingState, rowProcessingState,
session, session,
persistenceContext persistenceContext
); );
initializeEntity( instance, rowProcessingState, session, persistenceContext ); initializeEntity( instance, rowProcessingState, session, persistenceContext );
}
hibernateLazyInitializer.setImplementation( instance ); hibernateLazyInitializer.setImplementation( instance );
} }
else { else {
@ -674,7 +675,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
final Object entity = persistenceContext.getEntity( entityKey ); final Object entity = persistenceContext.getEntity( entityKey );
assert entity == null || entity == toInitialize; assert entity == null || entity == toInitialize;
//
// if ( entity != null ) { // if ( entity != null ) {
// return; // return;
// } // }

View File

@ -18,6 +18,7 @@ import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess; import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
@ -78,21 +79,26 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor ); final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor );
final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext(); final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
LoadingEntityEntry loadingEntityLocally = persistenceContext
.getLoadContexts().findLoadingEntityEntry( entityKey );
if ( loadingEntityLocally != null ) {
entityInstance = loadingEntityLocally.getEntityInstance();
}
else {
final Object entity = persistenceContext.getEntity( entityKey );
final Object proxy = persistenceContext.getProxy( entityKey ); final Object proxy = persistenceContext.getProxy( entityKey );
if ( entity != null && proxy != null && ( (HibernateProxy) proxy ).getHibernateLazyInitializer()
.isUninitialized() ) {
entityInstance = entity;
}
else {
if ( proxy != null ) { if ( proxy != null ) {
entityInstance = proxy; entityInstance = proxy;
} }
else { else {
final Object entity = persistenceContext.getEntity( entityKey );
if ( entity != null ) { if ( entity != null ) {
entityInstance = entity; entityInstance = entity;
} }
else {
LoadingEntityEntry loadingEntityLocally = rowProcessingState.getJdbcValuesSourceProcessingState()
.findLoadingEntityLocally( entityKey );
if ( loadingEntityLocally != null ) {
entityInstance = loadingEntityLocally.getEntityInstance();
}
else { else {
// Look into the second level cache if the descriptor is polymorphic // Look into the second level cache if the descriptor is polymorphic
final Object cachedEntity; final Object cachedEntity;
@ -112,7 +118,10 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
if ( cachedEntity != null ) { if ( cachedEntity != null ) {
entityInstance = cachedEntity; entityInstance = cachedEntity;
} }
else if ( concreteDescriptor.hasProxy() ) { else {
entityInstance = persistenceContext.getEntity( entityKey );
if ( entityInstance == null ) {
if ( concreteDescriptor.hasProxy() ) {
entityInstance = concreteDescriptor.createProxy( entityInstance = concreteDescriptor.createProxy(
identifier, identifier,
rowProcessingState.getSession() rowProcessingState.getSession()
@ -120,9 +129,17 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey ); persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
persistenceContext.addProxy( entityKey, entityInstance ); persistenceContext.addProxy( entityKey, entityInstance );
} }
else if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) { else if ( concreteDescriptor.getBytecodeEnhancementMetadata()
.isEnhancedForLazyLoading() ) {
entityInstance = concreteDescriptor.getBytecodeEnhancementMetadata() entityInstance = concreteDescriptor.getBytecodeEnhancementMetadata()
.createEnhancedProxy( entityKey, true, rowProcessingState.getSession() ); .createEnhancedProxy(
entityKey,
true,
rowProcessingState.getSession()
);
}
}
}
} }
} }
} }

View File

@ -9,7 +9,6 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.engine.spi.EntityUniqueKey; 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.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.UniqueKeyLoadable; import org.hibernate.persister.entity.UniqueKeyLoadable;

View File

@ -126,7 +126,7 @@ public class DeleteMultiLevelOrphansTest extends BaseCoreFunctionalTestCase {
results = session.createQuery( "from Preisregelung" ).list(); results = session.createQuery( "from Preisregelung" ).list();
assertEquals( 1, results.size() ); assertEquals( 1, results.size() );
Preisregelung preisregelung1Queried = (Preisregelung) results.get( 0 ); Preisregelung preisregelung1Queried = (Preisregelung) results.get( 0 );
assertEquals( tranchenmodellQueried, preisregelung1Queried.getTranchenmodell() ); assertEquals( preisregelung1Queried.getTranchenmodell(), tranchenmodellQueried );
results = session.createQuery( "from Tranche" ).list(); results = session.createQuery( "from Tranche" ).list();
assertEquals( 0, results.size() ); assertEquals( 0, results.size() );

View File

@ -14,13 +14,12 @@ import javax.persistence.OneToOne;
@Entity @Entity
public class Preisregelung { public class Preisregelung {
@Id
private Long id; private Long id;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private Tranchenmodell tranchenmodell; private Tranchenmodell tranchenmodell;
@Id
public Long getId() { public Long getId() {
return id; return id;
} }
@ -29,6 +28,7 @@ public class Preisregelung {
this.id = id; this.id = id;
} }
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
public Tranchenmodell getTranchenmodell() { public Tranchenmodell getTranchenmodell() {
return tranchenmodell; return tranchenmodell;
} }

View File

@ -18,17 +18,16 @@ import javax.persistence.OneToOne;
@Entity @Entity
public class Tranchenmodell { public class Tranchenmodell {
@Id
private Long id; private Long id;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "tranchenmodell", fetch = FetchType.LAZY, orphanRemoval = true)
private List<Tranche> tranchen = new ArrayList<Tranche>(); private List<Tranche> tranchen = new ArrayList<Tranche>();
@OneToOne(mappedBy="tranchenmodell", optional = true, fetch = FetchType.LAZY)
private Preisregelung preisregelung; private Preisregelung preisregelung;
@Id
public Long getId() { public Long getId() {
return id; return id;
} }
@ -37,10 +36,16 @@ public class Tranchenmodell {
this.id = id; this.id = id;
} }
@OneToMany(cascade = CascadeType.ALL, mappedBy = "tranchenmodell", fetch = FetchType.LAZY, orphanRemoval = true)
public List<Tranche> getTranchen() { public List<Tranche> getTranchen() {
return tranchen; return tranchen;
} }
public void setTranchen(List<Tranche> tranchen) {
this.tranchen = tranchen;
}
@OneToOne(mappedBy="tranchenmodell", optional = true, fetch = FetchType.LAZY)
public Preisregelung getPreisregelung() { public Preisregelung getPreisregelung() {
return preisregelung; return preisregelung;
} }