Skip to content

minor refactoring to DefaultRefreshEventListener #10421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,15 @@ protected void entityIsDetached(MergeEvent event, Object copiedId, Object origin
final Object id = getDetachedEntityId( event, originalId, persister );
// we must clone embedded composite identifiers, or we will get back the same instance that we pass in
// apply the special MERGE fetch profile and perform the resolution (Session#get)
final Object result = session.getLoadQueryInfluencers().fromInternalFetchProfile(
CascadingFetchProfile.MERGE,
() -> session.get( entityName, clonedIdentifier )
);
final Object result =
session.getLoadQueryInfluencers()
.fromInternalFetchProfile( CascadingFetchProfile.MERGE,
() -> session.get( entityName, clonedIdentifier ) );

if ( result == null ) {
LOG.trace( "Detached instance not found in database" );
// we got here because we assumed that an instance
// with an assigned id and no version was detached,
// with an assigned id and no version was detached
// when it was really transient (or deleted)
final Boolean knownTransient = persister.isTransient( entity, session );
if ( knownTransient == Boolean.FALSE ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.PersistenceContext;
Expand Down Expand Up @@ -62,41 +63,7 @@ public void onRefresh(RefreshEvent event, RefreshContext refreshedAlready) {
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
final Object object = event.getObject();
if ( persistenceContext.reassociateIfUninitializedProxy( object ) ) {
final boolean isTransient = isTransient( event, source, object );
// If refreshAlready is not empty then the refresh is the result of a
// cascade refresh and the refresh of the parent will take care of initializing the lazy
// entity and setting the correct lock on it, this is needed only when the refresh is called directly on a lazy entity
if ( refreshedAlready.isEmpty() ) {
final LazyInitializer lazyInitializer = extractLazyInitializer( object );
final EntityPersister persister;
if ( lazyInitializer != null ) {
persister = source.getEntityPersister( lazyInitializer.getEntityName(), object );
}
else if ( !isTransient ) {
persister = persistenceContext.getEntry( object ).getPersister();
}
else {
persister = source.getEntityPersister( source.guessEntityName( object ), object );
}

refresh(
event,
null,
source,
persister,
lazyInitializer,
null,
persister.getIdentifier( object, event.getSession() ),
persistenceContext
);
if ( lazyInitializer != null ) {
refreshedAlready.add( lazyInitializer.getImplementation() );
}
}

if ( isTransient ) {
source.setReadOnly( object, source.isDefaultReadOnly() );
}
handleUninitializedProxy( event, refreshedAlready, source, object, persistenceContext );
}
else {
final Object entity = persistenceContext.unproxyAndReassociate( object );
Expand All @@ -109,9 +76,58 @@ else if ( !isTransient ) {
}
}

private static void handleUninitializedProxy(
RefreshEvent event,
RefreshContext refreshedAlready,
EventSource source,
Object object,
PersistenceContext persistenceContext) {
final boolean isTransient = isTransient( event, source, object );
// If refreshAlready is nonempty then the refresh is the result of a cascade refresh and the
// refresh of the parent will take care of initializing the lazy entity and setting the
// correct lock. This is needed only when the refresh is called directly on a lazy entity.
if ( refreshedAlready.isEmpty() ) {
final LazyInitializer lazyInitializer = extractLazyInitializer( object );
final EntityPersister persister = getPersister( lazyInitializer, source, object, isTransient );
refresh(
event,
null,
source,
persister,
lazyInitializer,
null,
persister.getIdentifier( object, event.getSession() ),
persistenceContext
);
if ( lazyInitializer != null ) {
refreshedAlready.add( lazyInitializer.getImplementation() );
}
}

if ( isTransient ) {
source.setReadOnly( object, source.isDefaultReadOnly() );
}
}

private static EntityPersister getPersister(
LazyInitializer lazyInitializer,
EventSource source,
Object object,
boolean isTransient) {
if ( lazyInitializer != null ) {
return source.getEntityPersister( lazyInitializer.getEntityName(), object );
}
else if ( isTransient ) {
return source.getEntityPersister( source.guessEntityName( object ), object );
}
else {
return source.getPersistenceContextInternal().getEntry( object ).getPersister();
}
}

private static boolean isTransient(RefreshEvent event, EventSource source, Object object) {
final String entityName = event.getEntityName();
return entityName != null ? !source.contains( entityName, object) : !source.contains(object);
return entityName == null ? !source.contains( object ) : !source.contains( entityName, object );
}

private static void refresh(RefreshEvent event, RefreshContext refreshedAlready, Object object) {
Expand Down Expand Up @@ -179,25 +195,26 @@ private static void refresh(
Object object,
EventSource source,
EntityPersister persister,
LazyInitializer lazyInitializer,
LazyInitializer initializer,
EntityEntry entry,
Object id,
PersistenceContext persistenceContext) {
PersistenceContext context) {
if ( object != null ) {
final var instrumentationMetadata = persister.getBytecodeEnhancementMetadata();
if ( instrumentationMetadata.isEnhancedForLazyLoading() ) {
final var interceptor = instrumentationMetadata.extractInterceptor( object );
if ( interceptor != null ) {
// The list of initialized lazy fields have to be cleared in order to refresh them from the database.
// The list of initialized lazy fields has to be cleared
// before refreshing them from the database.
interceptor.clearInitializedLazyFields();
}
}
}

final Object result = source.getLoadQueryInfluencers().fromInternalFetchProfile(
CascadingFetchProfile.REFRESH,
() -> doRefresh( event, source, object, entry, persister, lazyInitializer, id, persistenceContext )
);
final Object result =
source.getLoadQueryInfluencers()
.fromInternalFetchProfile( CascadingFetchProfile.REFRESH,
() -> doRefresh( event, source, object, entry, persister, initializer, id, context ) );
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
}

Expand Down Expand Up @@ -241,7 +258,7 @@ private static Object doRefresh(
if ( currentLockMode.greaterThan( requestedLockMode ) ) {
// the requested lock-mode is less restrictive than the current one
// - pass along the current lock-mode (after accounting for WRITE)
lockOptionsToUse = event.getLockOptions().makeCopy();
lockOptionsToUse = lockOptionsToUse.makeCopy();
if ( currentLockMode == LockMode.WRITE
|| currentLockMode == LockMode.PESSIMISTIC_WRITE
|| currentLockMode == LockMode.PESSIMISTIC_READ ) {
Expand Down Expand Up @@ -272,7 +289,7 @@ private static Object doRefresh(

final Object result = persister.load( id, object, lockOptionsToUse, source );
if ( result != null ) {
// apply `postRefreshLockMode`, if needed
// apply postRefreshLockMode, if needed
if ( postRefreshLockMode != null ) {
// if we get here, there was a previous entry, and we need to reset its lock mode
// - however, the refresh operation actually creates a new entry, so get it
Expand Down Expand Up @@ -312,6 +329,7 @@ private static void evictCachedCollections(EntityPersister persister, Object id,
private static void evictCachedCollections(Type[] types, Object id, EventSource source)
throws HibernateException {
final SessionFactoryImplementor factory = source.getFactory();
final ActionQueue actionQueue = source.getActionQueue();
final MappingMetamodelImplementor metamodel = factory.getMappingMetamodel();
for ( Type type : types ) {
if ( type instanceof CollectionType collectionType ) {
Expand All @@ -327,7 +345,7 @@ private static void evictCachedCollections(Type[] types, Object id, EventSource
);
final SoftLock lock = cache.lockItem( source, ck, null );
cache.remove( source, ck );
source.getActionQueue().registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
actionQueue.registerProcess( (success, session) -> cache.unlockItem( session, ck, lock ) );
}
}
else if ( type instanceof ComponentType compositeType ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -925,10 +925,10 @@ public void refresh(String entityName, Object entity, LockMode lockMode) {
}
}

final Object result = getLoadQueryInfluencers().fromInternalFetchProfile(
CascadingFetchProfile.REFRESH,
() -> persister.load( id, entity, getNullSafeLockMode( lockMode ), this )
);
final Object result =
getLoadQueryInfluencers()
.fromInternalFetchProfile( CascadingFetchProfile.REFRESH,
() -> persister.load( id, entity, getNullSafeLockMode( lockMode ), this ) );
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
if ( temporaryPersistenceContext.isLoadFinished() ) {
temporaryPersistenceContext.clear();
Expand Down