Skip to content

Commit 356b7f5

Browse files
committed
HHH-18719 Previous row state reuse can provide detaches entities to the consumer
1 parent 96c61c3 commit 356b7f5

File tree

5 files changed

+39
-5
lines changed

5 files changed

+39
-5
lines changed

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,14 @@ public void clear() {
231231
if ( entitiesByKey != null ) {
232232
//Strictly avoid lambdas in this case
233233
for ( EntityHolderImpl value : entitiesByKey.values() ) {
234-
if ( value != null && value.proxy != null ) {
235-
extractLazyInitializer( value.proxy ).unsetSession();
234+
if ( value != null ) {
235+
value.state = EntityHolderState.DETACHED;
236+
if ( value.proxy != null ) {
237+
final LazyInitializer lazyInitializer = extractLazyInitializer( value.proxy );
238+
if ( lazyInitializer != null ) {
239+
lazyInitializer.unsetSession();
240+
}
241+
}
236242
}
237243
}
238244
}
@@ -2238,6 +2244,11 @@ public boolean isEventuallyInitialized() {
22382244
return state == EntityHolderState.INITIALIZED || entityInitializer != null;
22392245
}
22402246

2247+
@Override
2248+
public boolean isDetached() {
2249+
return state == EntityHolderState.DETACHED;
2250+
}
2251+
22412252
public static EntityHolderImpl forProxy(EntityKey entityKey, EntityPersister descriptor, Object proxy) {
22422253
return new EntityHolderImpl( entityKey, descriptor, null, proxy );
22432254
}
@@ -2250,7 +2261,8 @@ public static EntityHolderImpl forEntity(EntityKey entityKey, EntityPersister de
22502261
enum EntityHolderState {
22512262
UNINITIALIZED,
22522263
ENHANCED_PROXY,
2253-
INITIALIZED
2264+
INITIALIZED,
2265+
DETACHED
22542266
}
22552267

22562268
// NATURAL ID RESOLUTION HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2266,4 +2278,13 @@ public NaturalIdResolutions getNaturalIdResolutions() {
22662278
return naturalIdResolutions;
22672279
}
22682280

2281+
@Override
2282+
public EntityHolder detachEntity(EntityKey key) {
2283+
final EntityHolderImpl entityHolder = removeEntityHolder( key );
2284+
if ( entityHolder != null ) {
2285+
entityHolder.state = EntityHolderState.DETACHED;
2286+
}
2287+
return entityHolder;
2288+
}
2289+
22692290
}

hibernate-core/src/main/java/org/hibernate/engine/spi/EntityHolder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,9 @@ public interface EntityHolder {
6565
* Whether the entity is already initialized or will be initialized through an initializer eventually.
6666
*/
6767
boolean isEventuallyInitialized();
68+
69+
/**
70+
* Whether the entity is detached.
71+
*/
72+
boolean isDetached();
6873
}

hibernate-core/src/main/java/org/hibernate/engine/spi/PersistenceContext.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,4 +844,12 @@ EntityHolder claimEntityHolderIfPossible(
844844
* @return This persistence context's natural-id helper
845845
*/
846846
NaturalIdResolutions getNaturalIdResolutions();
847+
848+
/**
849+
Remove the {@link EntityHolder} and set its state to DETACHED
850+
*/
851+
default @Nullable EntityHolder detachEntity(EntityKey key) {
852+
EntityHolder entityHolder = removeEntityHolder( key );
853+
return entityHolder;
854+
}
847855
}

hibernate-core/src/main/java/org/hibernate/event/internal/DefaultEvictEventListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void onEvict(EvictEvent event) throws HibernateException {
5757
.getMappingMetamodel()
5858
.getEntityDescriptor( lazyInitializer.getEntityName() );
5959
final EntityKey key = source.generateEntityKey( id, persister );
60-
final EntityHolder holder = persistenceContext.removeEntityHolder( key );
60+
final EntityHolder holder = persistenceContext.detachEntity( key );
6161
// if the entity has been evicted then its holder is null
6262
if ( holder != null && !lazyInitializer.isUninitialized() ) {
6363
final Object entity = holder.getEntity();

hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ protected void resolveKey(EntityInitializerData data, boolean entityKeyOnly) {
578578
}
579579

580580
if ( oldEntityKey != null && previousRowReuse && oldEntityInstance != null
581-
&& areKeysEqual( oldEntityKey.getIdentifier(), id ) ) {
581+
&& areKeysEqual( oldEntityKey.getIdentifier(), id ) && !oldEntityHolder.isDetached() ) {
582582
data.setState( State.INITIALIZED );
583583
data.entityKey = oldEntityKey;
584584
data.setInstance( oldEntityInstance );

0 commit comments

Comments
 (0)