diff --git a/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java b/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java index 1e6c5109348b..9791b4098a24 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java @@ -7,10 +7,16 @@ package org.hibernate.engine.internal; import org.hibernate.LockMode; +import org.hibernate.engine.spi.EntityEntry; +import org.hibernate.engine.spi.EntityHolder; import org.hibernate.engine.spi.EntityKey; +import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.Status; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.proxy.LazyInitializer; + +import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** * Functionality relating to the Hibernate two-phase loading process, that may be reused by persisters @@ -39,16 +45,27 @@ public static void addUninitializedCachedEntity( final LockMode lockMode, final Object version, final SharedSessionContractImplementor session) { - session.getPersistenceContextInternal().addEntity( + final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); + final EntityHolder entityHolder = persistenceContext.addEntityHolder( key, object ); + final EntityEntry entityEntry = persistenceContext.addEntry( object, Status.LOADING, null, - key, + null, + key.getIdentifier(), version, lockMode, true, persister, false ); + entityHolder.setEntityEntry( entityEntry ); + final Object proxy = entityHolder.getProxy(); + if ( proxy != null ) { + // there is already a proxy for this impl + final LazyInitializer lazyInitializer = extractLazyInitializer( proxy ); + assert lazyInitializer != null; + lazyInitializer.setImplementation( object ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java index 833cc62b96f4..ecb4be773418 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java @@ -35,7 +35,7 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.pretty.MessageHelper; -import org.hibernate.proxy.HibernateProxy; +import org.hibernate.proxy.LazyInitializer; import org.hibernate.sql.results.LoadingLogger; import org.hibernate.stat.internal.StatsHelper; import org.hibernate.stat.spi.StatisticsImplementor; @@ -46,7 +46,8 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.isManagedEntity; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.Versioning.getVersion; -import static org.hibernate.loader.ast.internal.LoaderHelper.upgradeLock; +import static org.hibernate.loader.ast.internal.LoaderHelper.upgradeLock;; +import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** * @author Vlad Mihalcea @@ -388,7 +389,6 @@ private Object convertCacheEntryToEntity( EntityKey entityKey) { final SessionFactoryImplementor factory = source.getFactory(); - final EntityPersister subclassPersister; if ( LOG.isTraceEnabled() ) { LOG.tracef( @@ -398,19 +398,20 @@ private Object convertCacheEntryToEntity( ); } - final Object entity; + final EntityPersister subclassPersister = + factory.getRuntimeMetamodels().getMappingMetamodel() + .getEntityDescriptor( entry.getSubclass() ); + final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); + final EntityHolder oldHolder = persistenceContext.getEntityHolder( entityKey ); - subclassPersister = factory.getRuntimeMetamodels() - .getMappingMetamodel() - .getEntityDescriptor( entry.getSubclass() ); + final Object entity; if ( instanceToLoad != null ) { entity = instanceToLoad; } else { - final EntityHolder holder = source.getPersistenceContextInternal().getEntityHolder( entityKey ); - if ( holder != null && holder.getEntity() != null ) { + if ( oldHolder != null && oldHolder.getEntity() != null ) { // Use the entity which might already be - entity = holder.getEntity(); + entity = oldHolder.getEntity(); } else { entity = source.instantiate( subclassPersister, entityId ); @@ -430,23 +431,39 @@ private Object convertCacheEntryToEntity( } // make it circular-reference safe - TwoPhaseLoad.addUninitializedCachedEntity( - entityKey, - entity, - subclassPersister, - LockMode.NONE, - entry.getVersion(), - source - ); - - final PersistenceContext persistenceContext = source.getPersistenceContext(); - final Object[] values; - final Object version; + final EntityHolder holder = persistenceContext.addEntityHolder( entityKey, entity ); + final Object proxy = holder.getProxy(); final boolean isReadOnly; + if ( proxy != null ) { + // there is already a proxy for this impl + // only set the status to read-only if the proxy is read-only + final LazyInitializer lazyInitializer = extractLazyInitializer( proxy ); + assert lazyInitializer != null; + lazyInitializer.setImplementation( entity ); + + isReadOnly = lazyInitializer.isReadOnly(); + } + else { + isReadOnly = source.isDefaultReadOnly(); + } + holder.setEntityEntry( + persistenceContext.addEntry( + entity, + Status.LOADING, + null, + null, + entityKey.getIdentifier(), + entry.getVersion(), + LockMode.NONE, + true, + persister, + false + ) + ); final Type[] types = subclassPersister.getPropertyTypes(); // initializes the entity by (desired) side-effect - values = ( (StandardCacheEntryImpl) entry ).assemble( + final Object[] values = ( (StandardCacheEntryImpl) entry ).assemble( entity, entityId, subclassPersister, @@ -462,32 +479,23 @@ private Object convertCacheEntryToEntity( source ); } - version = getVersion( values, subclassPersister ); + final Object version = getVersion( values, subclassPersister ); LOG.tracef( "Cached Version : %s", version ); - final Object proxy = persistenceContext.getProxy( entityKey ); - if ( proxy != null ) { - // there is already a proxy for this impl - // only set the status to read-only if the proxy is read-only - isReadOnly = HibernateProxy.extractLazyInitializer( proxy ).isReadOnly(); - } - else { - isReadOnly = source.isDefaultReadOnly(); - } - - EntityEntry entityEntry = persistenceContext.addEntry( - entity, - ( isReadOnly ? Status.READ_ONLY : Status.MANAGED ), - values, - null, - entityId, - version, - LockMode.NONE, - true, - subclassPersister, - false + holder.setEntityEntry( + persistenceContext.addEntry( + entity, + isReadOnly ? Status.READ_ONLY : Status.MANAGED, + values, + null, + entityId, + version, + LockMode.NONE, + true, + subclassPersister, + false + ) ); - persistenceContext.getEntityHolder( entityKey ).setEntityEntry( entityEntry ); subclassPersister.afterInitialize( entity, source ); persistenceContext.initializeNonLazyCollections();