Skip to content

Commit bdd4d46

Browse files
committed
HHH-18689 Maintain proxy targets when converting cache entries
1 parent 3429499 commit bdd4d46

File tree

2 files changed

+72
-47
lines changed

2 files changed

+72
-47
lines changed

hibernate-core/src/main/java/org/hibernate/engine/internal/TwoPhaseLoad.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@
77
package org.hibernate.engine.internal;
88

99
import org.hibernate.LockMode;
10+
import org.hibernate.engine.spi.EntityEntry;
11+
import org.hibernate.engine.spi.EntityHolder;
1012
import org.hibernate.engine.spi.EntityKey;
13+
import org.hibernate.engine.spi.PersistenceContext;
1114
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1215
import org.hibernate.engine.spi.Status;
1316
import org.hibernate.persister.entity.EntityPersister;
17+
import org.hibernate.proxy.LazyInitializer;
18+
19+
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
1420

1521
/**
1622
* Functionality relating to the Hibernate two-phase loading process, that may be reused by persisters
@@ -39,16 +45,27 @@ public static void addUninitializedCachedEntity(
3945
final LockMode lockMode,
4046
final Object version,
4147
final SharedSessionContractImplementor session) {
42-
session.getPersistenceContextInternal().addEntity(
48+
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
49+
final EntityHolder entityHolder = persistenceContext.addEntityHolder( key, object );
50+
final EntityEntry entityEntry = persistenceContext.addEntry(
4351
object,
4452
Status.LOADING,
4553
null,
46-
key,
54+
null,
55+
key.getIdentifier(),
4756
version,
4857
lockMode,
4958
true,
5059
persister,
5160
false
5261
);
62+
entityHolder.setEntityEntry( entityEntry );
63+
final Object proxy = entityHolder.getProxy();
64+
if ( proxy != null ) {
65+
// there is already a proxy for this impl
66+
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
67+
assert lazyInitializer != null;
68+
lazyInitializer.setImplementation( object );
69+
}
5370
}
5471
}

hibernate-core/src/main/java/org/hibernate/loader/ast/internal/CacheEntityLoaderHelper.java

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import org.hibernate.internal.CoreMessageLogger;
3636
import org.hibernate.persister.entity.EntityPersister;
3737
import org.hibernate.pretty.MessageHelper;
38-
import org.hibernate.proxy.HibernateProxy;
38+
import org.hibernate.proxy.LazyInitializer;
3939
import org.hibernate.sql.results.LoadingLogger;
4040
import org.hibernate.stat.internal.StatsHelper;
4141
import org.hibernate.stat.spi.StatisticsImplementor;
@@ -47,6 +47,7 @@
4747
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
4848
import static org.hibernate.engine.internal.Versioning.getVersion;
4949
import static org.hibernate.loader.ast.internal.LoaderHelper.upgradeLock;
50+
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
5051

5152
/**
5253
* @author Vlad Mihalcea
@@ -388,7 +389,6 @@ private Object convertCacheEntryToEntity(
388389
EntityKey entityKey) {
389390

390391
final SessionFactoryImplementor factory = source.getFactory();
391-
final EntityPersister subclassPersister;
392392

393393
if ( LOG.isTraceEnabled() ) {
394394
LOG.tracef(
@@ -398,19 +398,20 @@ private Object convertCacheEntryToEntity(
398398
);
399399
}
400400

401-
final Object entity;
401+
final EntityPersister subclassPersister =
402+
factory.getRuntimeMetamodels().getMappingMetamodel()
403+
.getEntityDescriptor( entry.getSubclass() );
404+
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
405+
final EntityHolder oldHolder = persistenceContext.getEntityHolder( entityKey );
402406

403-
subclassPersister = factory.getRuntimeMetamodels()
404-
.getMappingMetamodel()
405-
.getEntityDescriptor( entry.getSubclass() );
407+
final Object entity;
406408
if ( instanceToLoad != null ) {
407409
entity = instanceToLoad;
408410
}
409411
else {
410-
final EntityHolder holder = source.getPersistenceContextInternal().getEntityHolder( entityKey );
411-
if ( holder != null && holder.getEntity() != null ) {
412+
if ( oldHolder != null && oldHolder.getEntity() != null ) {
412413
// Use the entity which might already be
413-
entity = holder.getEntity();
414+
entity = oldHolder.getEntity();
414415
}
415416
else {
416417
entity = source.instantiate( subclassPersister, entityId );
@@ -430,23 +431,39 @@ private Object convertCacheEntryToEntity(
430431
}
431432

432433
// make it circular-reference safe
433-
TwoPhaseLoad.addUninitializedCachedEntity(
434-
entityKey,
435-
entity,
436-
subclassPersister,
437-
LockMode.NONE,
438-
entry.getVersion(),
439-
source
440-
);
441-
442-
final PersistenceContext persistenceContext = source.getPersistenceContext();
443-
final Object[] values;
444-
final Object version;
434+
final EntityHolder holder = persistenceContext.addEntityHolder( entityKey, entity );
435+
final Object proxy = holder.getProxy();
445436
final boolean isReadOnly;
437+
if ( proxy != null ) {
438+
// there is already a proxy for this impl
439+
// only set the status to read-only if the proxy is read-only
440+
final LazyInitializer lazyInitializer = extractLazyInitializer( proxy );
441+
assert lazyInitializer != null;
442+
lazyInitializer.setImplementation( entity );
443+
444+
isReadOnly = lazyInitializer.isReadOnly();
445+
}
446+
else {
447+
isReadOnly = source.isDefaultReadOnly();
448+
}
449+
holder.setEntityEntry(
450+
persistenceContext.addEntry(
451+
entity,
452+
Status.LOADING,
453+
null,
454+
null,
455+
entityKey.getIdentifier(),
456+
entry.getVersion(),
457+
LockMode.NONE,
458+
true,
459+
persister,
460+
false
461+
)
462+
);
446463

447464
final Type[] types = subclassPersister.getPropertyTypes();
448465
// initializes the entity by (desired) side-effect
449-
values = ( (StandardCacheEntryImpl) entry ).assemble(
466+
final Object[] values = ( (StandardCacheEntryImpl) entry ).assemble(
450467
entity,
451468
entityId,
452469
subclassPersister,
@@ -462,32 +479,23 @@ private Object convertCacheEntryToEntity(
462479
source
463480
);
464481
}
465-
version = getVersion( values, subclassPersister );
482+
final Object version = getVersion( values, subclassPersister );
466483
LOG.tracef( "Cached Version : %s", version );
467484

468-
final Object proxy = persistenceContext.getProxy( entityKey );
469-
if ( proxy != null ) {
470-
// there is already a proxy for this impl
471-
// only set the status to read-only if the proxy is read-only
472-
isReadOnly = HibernateProxy.extractLazyInitializer( proxy ).isReadOnly();
473-
}
474-
else {
475-
isReadOnly = source.isDefaultReadOnly();
476-
}
477-
478-
EntityEntry entityEntry = persistenceContext.addEntry(
479-
entity,
480-
( isReadOnly ? Status.READ_ONLY : Status.MANAGED ),
481-
values,
482-
null,
483-
entityId,
484-
version,
485-
LockMode.NONE,
486-
true,
487-
subclassPersister,
488-
false
485+
holder.setEntityEntry(
486+
persistenceContext.addEntry(
487+
entity,
488+
isReadOnly ? Status.READ_ONLY : Status.MANAGED,
489+
values,
490+
null,
491+
entityId,
492+
version,
493+
LockMode.NONE,
494+
true,
495+
subclassPersister,
496+
false
497+
)
489498
);
490-
persistenceContext.getEntityHolder( entityKey ).setEntityEntry( entityEntry );
491499
subclassPersister.afterInitialize( entity, source );
492500
persistenceContext.initializeNonLazyCollections();
493501

0 commit comments

Comments
 (0)