1515import org .hibernate .cache .spi .access .SoftLock ;
1616import org .hibernate .engine .internal .Cascade ;
1717import org .hibernate .engine .internal .CascadePoint ;
18+ import org .hibernate .engine .spi .ActionQueue ;
1819import org .hibernate .engine .spi .CascadingActions ;
1920import org .hibernate .engine .spi .EntityEntry ;
2021import org .hibernate .engine .spi .PersistenceContext ;
@@ -62,41 +63,7 @@ public void onRefresh(RefreshEvent event, RefreshContext refreshedAlready) {
6263 final PersistenceContext persistenceContext = source .getPersistenceContextInternal ();
6364 final Object object = event .getObject ();
6465 if ( persistenceContext .reassociateIfUninitializedProxy ( object ) ) {
65- final boolean isTransient = isTransient ( event , source , object );
66- // If refreshAlready is not empty then the refresh is the result of a
67- // cascade refresh and the refresh of the parent will take care of initializing the lazy
68- // entity and setting the correct lock on it, this is needed only when the refresh is called directly on a lazy entity
69- if ( refreshedAlready .isEmpty () ) {
70- final LazyInitializer lazyInitializer = extractLazyInitializer ( object );
71- final EntityPersister persister ;
72- if ( lazyInitializer != null ) {
73- persister = source .getEntityPersister ( lazyInitializer .getEntityName (), object );
74- }
75- else if ( !isTransient ) {
76- persister = persistenceContext .getEntry ( object ).getPersister ();
77- }
78- else {
79- persister = source .getEntityPersister ( source .guessEntityName ( object ), object );
80- }
81-
82- refresh (
83- event ,
84- null ,
85- source ,
86- persister ,
87- lazyInitializer ,
88- null ,
89- persister .getIdentifier ( object , event .getSession () ),
90- persistenceContext
91- );
92- if ( lazyInitializer != null ) {
93- refreshedAlready .add ( lazyInitializer .getImplementation () );
94- }
95- }
96-
97- if ( isTransient ) {
98- source .setReadOnly ( object , source .isDefaultReadOnly () );
99- }
66+ handleUninitializedProxy ( event , refreshedAlready , source , object , persistenceContext );
10067 }
10168 else {
10269 final Object entity = persistenceContext .unproxyAndReassociate ( object );
@@ -109,9 +76,58 @@ else if ( !isTransient ) {
10976 }
11077 }
11178
79+ private static void handleUninitializedProxy (
80+ RefreshEvent event ,
81+ RefreshContext refreshedAlready ,
82+ EventSource source ,
83+ Object object ,
84+ PersistenceContext persistenceContext ) {
85+ final boolean isTransient = isTransient ( event , source , object );
86+ // If refreshAlready is nonempty then the refresh is the result of a cascade refresh and the
87+ // refresh of the parent will take care of initializing the lazy entity and setting the
88+ // correct lock. This is needed only when the refresh is called directly on a lazy entity.
89+ if ( refreshedAlready .isEmpty () ) {
90+ final LazyInitializer lazyInitializer = extractLazyInitializer ( object );
91+ final EntityPersister persister = getPersister ( lazyInitializer , source , object , isTransient );
92+ refresh (
93+ event ,
94+ null ,
95+ source ,
96+ persister ,
97+ lazyInitializer ,
98+ null ,
99+ persister .getIdentifier ( object , event .getSession () ),
100+ persistenceContext
101+ );
102+ if ( lazyInitializer != null ) {
103+ refreshedAlready .add ( lazyInitializer .getImplementation () );
104+ }
105+ }
106+
107+ if ( isTransient ) {
108+ source .setReadOnly ( object , source .isDefaultReadOnly () );
109+ }
110+ }
111+
112+ private static EntityPersister getPersister (
113+ LazyInitializer lazyInitializer ,
114+ EventSource source ,
115+ Object object ,
116+ boolean isTransient ) {
117+ if ( lazyInitializer != null ) {
118+ return source .getEntityPersister ( lazyInitializer .getEntityName (), object );
119+ }
120+ else if ( isTransient ) {
121+ return source .getEntityPersister ( source .guessEntityName ( object ), object );
122+ }
123+ else {
124+ return source .getPersistenceContextInternal ().getEntry ( object ).getPersister ();
125+ }
126+ }
127+
112128 private static boolean isTransient (RefreshEvent event , EventSource source , Object object ) {
113129 final String entityName = event .getEntityName ();
114- return entityName != null ? !source .contains ( entityName , object ) : !source .contains (object );
130+ return entityName == null ? !source .contains ( object ) : !source .contains ( entityName , object );
115131 }
116132
117133 private static void refresh (RefreshEvent event , RefreshContext refreshedAlready , Object object ) {
@@ -179,25 +195,26 @@ private static void refresh(
179195 Object object ,
180196 EventSource source ,
181197 EntityPersister persister ,
182- LazyInitializer lazyInitializer ,
198+ LazyInitializer initializer ,
183199 EntityEntry entry ,
184200 Object id ,
185- PersistenceContext persistenceContext ) {
201+ PersistenceContext context ) {
186202 if ( object != null ) {
187203 final var instrumentationMetadata = persister .getBytecodeEnhancementMetadata ();
188204 if ( instrumentationMetadata .isEnhancedForLazyLoading () ) {
189205 final var interceptor = instrumentationMetadata .extractInterceptor ( object );
190206 if ( interceptor != null ) {
191- // The list of initialized lazy fields have to be cleared in order to refresh them from the database.
207+ // The list of initialized lazy fields has to be cleared
208+ // before refreshing them from the database.
192209 interceptor .clearInitializedLazyFields ();
193210 }
194211 }
195212 }
196213
197- final Object result = source . getLoadQueryInfluencers (). fromInternalFetchProfile (
198- CascadingFetchProfile . REFRESH ,
199- () -> doRefresh ( event , source , object , entry , persister , lazyInitializer , id , persistenceContext )
200- );
214+ final Object result =
215+ source . getLoadQueryInfluencers ()
216+ . fromInternalFetchProfile ( CascadingFetchProfile . REFRESH ,
217+ () -> doRefresh ( event , source , object , entry , persister , initializer , id , context ) );
201218 UnresolvableObjectException .throwIfNull ( result , id , persister .getEntityName () );
202219 }
203220
@@ -241,7 +258,7 @@ private static Object doRefresh(
241258 if ( currentLockMode .greaterThan ( requestedLockMode ) ) {
242259 // the requested lock-mode is less restrictive than the current one
243260 // - pass along the current lock-mode (after accounting for WRITE)
244- lockOptionsToUse = event . getLockOptions () .makeCopy ();
261+ lockOptionsToUse = lockOptionsToUse .makeCopy ();
245262 if ( currentLockMode == LockMode .WRITE
246263 || currentLockMode == LockMode .PESSIMISTIC_WRITE
247264 || currentLockMode == LockMode .PESSIMISTIC_READ ) {
@@ -272,7 +289,7 @@ private static Object doRefresh(
272289
273290 final Object result = persister .load ( id , object , lockOptionsToUse , source );
274291 if ( result != null ) {
275- // apply ` postRefreshLockMode` , if needed
292+ // apply postRefreshLockMode, if needed
276293 if ( postRefreshLockMode != null ) {
277294 // if we get here, there was a previous entry, and we need to reset its lock mode
278295 // - however, the refresh operation actually creates a new entry, so get it
@@ -312,6 +329,7 @@ private static void evictCachedCollections(EntityPersister persister, Object id,
312329 private static void evictCachedCollections (Type [] types , Object id , EventSource source )
313330 throws HibernateException {
314331 final SessionFactoryImplementor factory = source .getFactory ();
332+ final ActionQueue actionQueue = source .getActionQueue ();
315333 final MappingMetamodelImplementor metamodel = factory .getMappingMetamodel ();
316334 for ( Type type : types ) {
317335 if ( type instanceof CollectionType collectionType ) {
@@ -327,7 +345,7 @@ private static void evictCachedCollections(Type[] types, Object id, EventSource
327345 );
328346 final SoftLock lock = cache .lockItem ( source , ck , null );
329347 cache .remove ( source , ck );
330- source . getActionQueue () .registerProcess ( (success , session ) -> cache .unlockItem ( session , ck , lock ) );
348+ actionQueue .registerProcess ( (success , session ) -> cache .unlockItem ( session , ck , lock ) );
331349 }
332350 }
333351 else if ( type instanceof ComponentType compositeType ) {
0 commit comments