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,15 +480,13 @@ 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, session,
session, persistenceContext
persistenceContext );
);
}
} }
if ( LockMode.NONE != lockMode ) { if ( LockMode.NONE != lockMode ) {
@ -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 );
entityKey.getIdentifier(), if ( instance == null ) {
rowProcessingState, instance = resolveInstance(
session, entityKey.getIdentifier(),
persistenceContext rowProcessingState,
); session,
initializeEntity( instance, rowProcessingState, session, persistenceContext ); 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,51 +79,67 @@ 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();
final Object proxy = persistenceContext.getProxy( entityKey ); LoadingEntityEntry loadingEntityLocally = persistenceContext
if ( proxy != null ) { .getLoadContexts().findLoadingEntityEntry( entityKey );
entityInstance = proxy; if ( loadingEntityLocally != null ) {
entityInstance = loadingEntityLocally.getEntityInstance();
} }
else { else {
final Object entity = persistenceContext.getEntity( entityKey ); final Object entity = persistenceContext.getEntity( entityKey );
if ( entity != null ) { final Object proxy = persistenceContext.getProxy( entityKey );
if ( entity != null && proxy != null && ( (HibernateProxy) proxy ).getHibernateLazyInitializer()
.isUninitialized() ) {
entityInstance = entity; entityInstance = entity;
} }
else { else {
LoadingEntityEntry loadingEntityLocally = rowProcessingState.getJdbcValuesSourceProcessingState() if ( proxy != null ) {
.findLoadingEntityLocally( entityKey ); entityInstance = proxy;
if ( loadingEntityLocally != null ) {
entityInstance = loadingEntityLocally.getEntityInstance();
} }
else { else {
// Look into the second level cache if the descriptor is polymorphic if ( entity != null ) {
final Object cachedEntity; entityInstance = entity;
if ( concreteDescriptor.getEntityMetamodel().hasSubclasses() ) {
cachedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache(
(EventSource) rowProcessingState.getSession(),
null,
LockMode.NONE,
concreteDescriptor,
entityKey
);
} }
else { else {
cachedEntity = null; // Look into the second level cache if the descriptor is polymorphic
} final Object cachedEntity;
if ( concreteDescriptor.getEntityMetamodel().hasSubclasses() ) {
cachedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache(
(EventSource) rowProcessingState.getSession(),
null,
LockMode.NONE,
concreteDescriptor,
entityKey
);
}
else {
cachedEntity = null;
}
if ( cachedEntity != null ) { if ( cachedEntity != null ) {
entityInstance = cachedEntity; entityInstance = cachedEntity;
} }
else if ( concreteDescriptor.hasProxy() ) { else {
entityInstance = concreteDescriptor.createProxy( entityInstance = persistenceContext.getEntity( entityKey );
identifier, if ( entityInstance == null ) {
rowProcessingState.getSession() if ( concreteDescriptor.hasProxy() ) {
); entityInstance = concreteDescriptor.createProxy(
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey ); identifier,
persistenceContext.addProxy( entityKey, entityInstance ); rowProcessingState.getSession()
} );
else if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) { persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
entityInstance = concreteDescriptor.getBytecodeEnhancementMetadata() persistenceContext.addProxy( entityKey, entityInstance );
.createEnhancedProxy( entityKey, true, rowProcessingState.getSession() ); }
else if ( concreteDescriptor.getBytecodeEnhancementMetadata()
.isEnhancedForLazyLoading() ) {
entityInstance = concreteDescriptor.getBytecodeEnhancementMetadata()
.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;
} }