HHH-15651 StatefulPersistenceContext#clear shouldn't need defensive copies for iteration

This commit is contained in:
Sanne Grinovero 2022-11-01 16:51:21 +00:00 committed by Sanne Grinovero
parent 001de2b203
commit cdbf92fd71
2 changed files with 19 additions and 4 deletions

View File

@ -22,6 +22,7 @@
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer;
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity; import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
import static org.hibernate.engine.internal.ManagedTypeHelper.isManaged; import static org.hibernate.engine.internal.ManagedTypeHelper.isManaged;
@ -329,6 +330,18 @@ public Map.Entry<Object, EntityEntry>[] reentrantSafeEntityEntries() {
return reentrantSafeEntries; return reentrantSafeEntries;
} }
/**
* Not reentrant like #reentrantSafeEntityEntries but most likely
* the more efficient choice, when reentrant safety isn't required.
*/
public void processEachEntity(final Consumer<Object> entityProcessor) {
ManagedEntity managedEntity = head;
while ( managedEntity != null ) {
entityProcessor.accept( managedEntity.$$_hibernate_getEntityInstance() );
managedEntity = managedEntity.$$_hibernate_getNextManagedEntity();
}
}
/** /**
* Clear this context of all managed entities * Clear this context of all managed entities
*/ */

View File

@ -232,10 +232,7 @@ public void clear() {
} ); } );
} }
for ( Entry<Object, EntityEntry> objectEntityEntryEntry : entityEntryContext.reentrantSafeEntityEntries() ) {//TODO make this a forEach process within the container entityEntryContext.processEachEntity( StatefulPersistenceContext::processEntityOnClear );
//type-cache-pollution agent: always check for EnhancedEntity type first.
ManagedTypeHelper.processIfPersistentAttributeInterceptable( objectEntityEntryEntry.getKey(), StatefulPersistenceContext::unsetSession, null );
}
final SharedSessionContractImplementor session = getSession(); final SharedSessionContractImplementor session = getSession();
if ( collectionEntries != null ) { if ( collectionEntries != null ) {
@ -266,6 +263,11 @@ public void clear() {
naturalIdResolutions = null; naturalIdResolutions = null;
} }
private static void processEntityOnClear(final Object entity) {
//type-cache-pollution agent: always check for EnhancedEntity type first.
ManagedTypeHelper.processIfPersistentAttributeInterceptable( entity, StatefulPersistenceContext::unsetSession, null );
}
private static void unsetSession(PersistentAttributeInterceptable persistentAttributeInterceptable, Object ignoredParam) { private static void unsetSession(PersistentAttributeInterceptable persistentAttributeInterceptable, Object ignoredParam) {
final PersistentAttributeInterceptor interceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor(); final PersistentAttributeInterceptor interceptor = persistentAttributeInterceptable.$$_hibernate_getInterceptor();
if ( interceptor instanceof LazyAttributeLoadingInterceptor ) { if ( interceptor instanceof LazyAttributeLoadingInterceptor ) {