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

View File

@ -18,6 +18,7 @@ import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.graph.AbstractFetchParentAccess;
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 PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
final Object proxy = persistenceContext.getProxy( entityKey );
if ( proxy != null ) {
entityInstance = proxy;
LoadingEntityEntry loadingEntityLocally = persistenceContext
.getLoadContexts().findLoadingEntityEntry( entityKey );
if ( loadingEntityLocally != null ) {
entityInstance = loadingEntityLocally.getEntityInstance();
}
else {
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;
}
else {
LoadingEntityEntry loadingEntityLocally = rowProcessingState.getJdbcValuesSourceProcessingState()
.findLoadingEntityLocally( entityKey );
if ( loadingEntityLocally != null ) {
entityInstance = loadingEntityLocally.getEntityInstance();
if ( proxy != null ) {
entityInstance = proxy;
}
else {
// 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
);
if ( entity != null ) {
entityInstance = entity;
}
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 ) {
entityInstance = cachedEntity;
}
else if ( concreteDescriptor.hasProxy() ) {
entityInstance = concreteDescriptor.createProxy(
identifier,
rowProcessingState.getSession()
);
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
persistenceContext.addProxy( entityKey, entityInstance );
}
else if ( concreteDescriptor.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() ) {
entityInstance = concreteDescriptor.getBytecodeEnhancementMetadata()
.createEnhancedProxy( entityKey, true, rowProcessingState.getSession() );
if ( cachedEntity != null ) {
entityInstance = cachedEntity;
}
else {
entityInstance = persistenceContext.getEntity( entityKey );
if ( entityInstance == null ) {
if ( concreteDescriptor.hasProxy() ) {
entityInstance = concreteDescriptor.createProxy(
identifier,
rowProcessingState.getSession()
);
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
persistenceContext.addProxy( entityKey, entityInstance );
}
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.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.UniqueKeyLoadable;

View File

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

View File

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

View File

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