Skip to content

Commit 2555a05

Browse files
dreab8beikov
authored andcommitted
HHH-1645 HHH-17395 Refresh with LockMode on an unitialized proxy does not work
1 parent 49190fd commit 2555a05

File tree

3 files changed

+61
-17
lines changed

3 files changed

+61
-17
lines changed

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

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
3333
import org.hibernate.persister.collection.CollectionPersister;
3434
import org.hibernate.persister.entity.EntityPersister;
35+
import org.hibernate.proxy.HibernateProxy;
36+
import org.hibernate.proxy.LazyInitializer;
3537
import org.hibernate.type.CollectionType;
3638
import org.hibernate.type.CompositeType;
3739
import org.hibernate.type.Type;
@@ -61,7 +63,22 @@ public void onRefresh(RefreshEvent event, RefreshContext refreshedAlready) {
6163
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
6264
final Object object = event.getObject();
6365
if ( persistenceContext.reassociateIfUninitializedProxy( object ) ) {
64-
if ( isTransient( event, source, object ) ) {
66+
final boolean isTransient = isTransient( event, source, object );
67+
68+
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( object );
69+
final EntityPersister persister = source.getEntityPersister( lazyInitializer.getEntityName(), object );
70+
refresh(
71+
event,
72+
null,
73+
source,
74+
persister,
75+
lazyInitializer,
76+
null,
77+
persister.getIdentifier( object, event.getSession() ),
78+
persistenceContext
79+
);
80+
81+
if ( isTransient ) {
6582
source.setReadOnly( object, source.isDefaultReadOnly() );
6683
}
6784
}
@@ -147,9 +164,22 @@ private static void refresh(RefreshEvent event, RefreshContext refreshedAlready,
147164
evictEntity( object, persister, id, source );
148165
evictCachedCollections( persister, id, source );
149166

167+
refresh( event, object, source, persister, null, entry, id, persistenceContext );
168+
}
169+
170+
private static void refresh(
171+
RefreshEvent event,
172+
Object object,
173+
EventSource source,
174+
EntityPersister persister,
175+
LazyInitializer lazyInitializer,
176+
EntityEntry entry,
177+
Object id,
178+
PersistenceContext persistenceContext) {
179+
150180
final Object result = source.getLoadQueryInfluencers().fromInternalFetchProfile(
151181
CascadingFetchProfile.REFRESH,
152-
() -> doRefresh( event, source, object, entry, persister, id, persistenceContext )
182+
() -> doRefresh( event, source, object, entry, persister, lazyInitializer, id, persistenceContext )
153183
);
154184
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
155185
}
@@ -182,6 +212,7 @@ private static Object doRefresh(
182212
Object object,
183213
EntityEntry entry,
184214
EntityPersister persister,
215+
LazyInitializer lazyInitializer,
185216
Object id,
186217
PersistenceContext persistenceContext) {
187218
// Handle the requested lock-mode (if one) in relation to the entry's (if one) current lock-mode
@@ -231,19 +262,32 @@ private static Object doRefresh(
231262
persistenceContext.getEntry( result ).setLockMode( postRefreshLockMode );
232263
}
233264

234-
// Keep the same read-only/modifiable setting for the entity that it had before refreshing;
235-
// If it was transient, then set it to the default for the source.
236-
if ( !persister.isMutable() ) {
237-
// this is probably redundant; it should already be read-only
238-
source.setReadOnly( result, true );
239-
}
240-
else {
241-
source.setReadOnly( result, entry == null ? source.isDefaultReadOnly() : entry.isReadOnly() );
242-
}
265+
source.setReadOnly( result, isReadOnly( entry, persister, lazyInitializer, source ) );
243266
}
244267
return result;
245268
}
246269

270+
private static boolean isReadOnly(
271+
EntityEntry entry,
272+
EntityPersister persister,
273+
LazyInitializer lazyInitializer,
274+
EventSource source) {
275+
// Keep the same read-only/modifiable setting for the entity that it had before refreshing;
276+
// If it was transient, then set it to the default for the source.
277+
if ( !persister.isMutable() ) {
278+
return true;
279+
}
280+
else if ( entry != null ) {
281+
return entry.isReadOnly();
282+
}
283+
else if ( lazyInitializer != null ) {
284+
return lazyInitializer.isReadOnly();
285+
}
286+
else {
287+
return source.isDefaultReadOnly();
288+
}
289+
}
290+
247291
private static void evictCachedCollections(EntityPersister persister, Object id, EventSource source) {
248292
evictCachedCollections( persister.getPropertyTypes(), id, source );
249293
}

hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlyProxyTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ public void testReadOnlyRefresh(SessionFactoryScope scope) {
11021102
s.setReadOnly( dp, true );
11031103
assertFalse( Hibernate.isInitialized( dp ) );
11041104
s.refresh( dp );
1105-
assertFalse( Hibernate.isInitialized( dp ) );
1105+
assertTrue( Hibernate.isInitialized( dp ) );
11061106
assertEquals( "original", dp.getDescription() );
11071107
assertTrue( Hibernate.isInitialized( dp ) );
11081108
dp.setDescription( "changed" );
@@ -1232,7 +1232,7 @@ public void testReadOnlyRefreshDetached(SessionFactoryScope scope) {
12321232
assertTrue( s.isReadOnly( dp ) );
12331233
s.evict( dp );
12341234
s.refresh( dp );
1235-
assertFalse( Hibernate.isInitialized( dp ) );
1235+
assertTrue( Hibernate.isInitialized( dp ) );
12361236
assertFalse( s.isReadOnly( dp ) );
12371237
dp.setDescription( "changed" );
12381238
assertEquals( "changed", dp.getDescription() );

hibernate-core/src/test/java/org/hibernate/orm/test/readonly/ReadOnlySessionTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -516,11 +516,11 @@ public void testReadOnlyProxyRefresh(SessionFactoryScope scope) {
516516
assertTrue( s.isReadOnly( dp ) );
517517
assertFalse( Hibernate.isInitialized( dp ) );
518518
s.refresh( dp );
519-
assertFalse( Hibernate.isInitialized( dp ) );
519+
assertTrue( Hibernate.isInitialized( dp ) );
520520
assertTrue( s.isReadOnly( dp ) );
521521
s.setDefaultReadOnly( false );
522522
s.refresh( dp );
523-
assertFalse( Hibernate.isInitialized( dp ) );
523+
assertTrue( Hibernate.isInitialized( dp ) );
524524
assertTrue( s.isReadOnly( dp ) );
525525
assertEquals( "original", dp.getDescription() );
526526
assertTrue( Hibernate.isInitialized( dp ) );
@@ -574,12 +574,12 @@ public void testReadOnlyProxyRefreshDetached(SessionFactoryScope scope) {
574574
assertTrue( s.isReadOnly( dp ) );
575575
s.evict( dp );
576576
s.refresh( dp );
577-
assertFalse( Hibernate.isInitialized( dp ) );
577+
assertTrue( Hibernate.isInitialized( dp ) );
578578
s.setDefaultReadOnly( false );
579579
assertTrue( s.isReadOnly( dp ) );
580580
s.evict( dp );
581581
s.refresh( dp );
582-
assertFalse( Hibernate.isInitialized( dp ) );
582+
assertTrue( Hibernate.isInitialized( dp ) );
583583
assertFalse( s.isReadOnly( dp ) );
584584
assertFalse( s.isReadOnly( ( (HibernateProxy) dp ).getHibernateLazyInitializer().getImplementation() ) );
585585
dp.setDescription( "changed" );

0 commit comments

Comments
 (0)