Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 75bd505

Browse files
committed
HHH-19605 Fix entity dirtiness logic when dealing with proxies
1 parent 15dc518 commit 75bd505

File tree

2 files changed

+36
-29
lines changed

2 files changed

+36
-29
lines changed

‎hibernate-core/src/main/java/org/hibernate/engine/internal/EntityEntryImpl.java

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
import org.hibernate.engine.spi.EntityKey;
2121
import org.hibernate.engine.spi.ManagedEntity;
2222
import org.hibernate.engine.spi.PersistenceContext;
23+
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
2324
import org.hibernate.engine.spi.SelfDirtinessTracker;
2425
import org.hibernate.engine.spi.SessionImplementor;
2526
import org.hibernate.engine.spi.SharedSessionContractImplementor;
2627
import org.hibernate.engine.spi.Status;
2728
import org.hibernate.internal.util.ImmutableBitSet;
2829
import org.hibernate.persister.entity.EntityPersister;
30+
import org.hibernate.proxy.LazyInitializer;
2931
import org.hibernate.type.TypeHelper;
3032

3133
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -37,10 +39,8 @@
3739
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.PREVIOUS_STATUS;
3840
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.STATUS;
3941
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
40-
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
42+
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptableOrNull;
4143
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker;
42-
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
43-
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
4444
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker;
4545
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfManagedEntity;
4646
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirtinessTracker;
@@ -385,9 +385,17 @@ private boolean isUnequivocallyNonDirty(Object entity) {
385385
}
386386

387387
private boolean isNonDirtyViaCustomStrategy(Object entity) {
388-
if ( isPersistentAttributeInterceptable( entity ) ) {
389-
if ( asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor()
390-
instanceof EnhancementAsProxyLazinessInterceptor ) {
388+
final PersistentAttributeInterceptable interceptable = asPersistentAttributeInterceptableOrNull( entity );
389+
if ( interceptable != null ) {
390+
if ( interceptable.$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor interceptor
391+
&& !interceptor.isInitialized() ) {
392+
// we never have to check an uninitialized proxy
393+
return true;
394+
}
395+
}
396+
else {
397+
final LazyInitializer lazyInitializer = extractLazyInitializer( entity );
398+
if ( lazyInitializer != null && lazyInitializer.isUninitialized() ) {
391399
// we never have to check an uninitialized proxy
392400
return true;
393401
}
@@ -400,28 +408,24 @@ private boolean isNonDirtyViaCustomStrategy(Object entity) {
400408
}
401409

402410
private boolean isNonDirtyViaTracker(Object entity) {
403-
final boolean uninitializedProxy;
404-
if ( isPersistentAttributeInterceptable( entity ) ) {
405-
if ( asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor()
406-
instanceof EnhancementAsProxyLazinessInterceptor lazinessInterceptor ) {
407-
return !lazinessInterceptor.hasWrittenFieldNames();
411+
final PersistentAttributeInterceptable interceptable = asPersistentAttributeInterceptableOrNull( entity );
412+
if ( interceptable != null ) {
413+
if ( interceptable.$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor interceptor ) {
414+
return !interceptor.hasWrittenFieldNames();
408415
}
409-
else {
410-
uninitializedProxy = false;
411-
}
412-
}
413-
else if ( isHibernateProxy( entity ) ) {
414-
uninitializedProxy = extractLazyInitializer( entity ).isUninitialized();
415416
}
416417
else {
417-
uninitializedProxy = false;
418+
final LazyInitializer lazyInitializer = extractLazyInitializer( entity );
419+
if ( lazyInitializer != null && lazyInitializer.isUninitialized() ) {
420+
// we never have to check an uninitialized proxy
421+
return true;
422+
}
418423
}
419424
// we never have to check an uninitialized proxy
420-
return uninitializedProxy
421-
|| !persister.hasCollections()
422-
&& !persister.hasMutableProperties()
423-
&& !asSelfDirtinessTracker( entity ).$$_hibernate_hasDirtyAttributes()
424-
&& asManagedEntity( entity ).$$_hibernate_useTracker();
425+
return !persister.hasCollections()
426+
&& !persister.hasMutableProperties()
427+
&& asManagedEntity( entity ).$$_hibernate_useTracker()
428+
&& !asSelfDirtinessTracker( entity ).$$_hibernate_hasDirtyAttributes();
425429
}
426430

427431
@Override

‎hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDirtyCheckEventListener.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import org.hibernate.persister.collection.CollectionPersister;
1717
import org.hibernate.persister.entity.EntityPersister;
1818

19+
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
20+
1921

2022
/**
2123
* Determines if the current session holds modified state which
@@ -61,22 +63,23 @@ public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
6163

6264
private static boolean isEntityDirty(EntityHolder holder, EventSource session) {
6365
final var entityEntry = holder.getEntityEntry();
64-
final Status status = entityEntry.getStatus();
66+
final Status status = castNonNull( entityEntry ).getStatus();
6567
return switch ( status ) {
6668
case GONE, READ_ONLY -> false;
6769
case DELETED -> true;
68-
case MANAGED -> isManagedEntityDirty( holder.getManagedObject(), holder.getDescriptor(), entityEntry, session );
70+
case MANAGED -> isManagedEntityDirty( holder, entityEntry, session );
6971
case SAVING, LOADING -> throw new AssertionFailure( "Unexpected status: " + status );
7072
};
7173
}
7274

73-
private static boolean isManagedEntityDirty(
74-
Object entity, EntityPersister descriptor, EntityEntry entityEntry, EventSource session) {
75-
if ( entityEntry.requiresDirtyCheck( entity ) ) { // takes into account CustomEntityDirtinessStrategy
75+
private static boolean isManagedEntityDirty(EntityHolder holder, EntityEntry entityEntry, EventSource session) {
76+
if ( entityEntry.requiresDirtyCheck( holder.getManagedObject() ) ) { // takes into account CustomEntityDirtinessStrategy
77+
final Object entity = holder.getEntity();
78+
final EntityPersister descriptor = holder.getDescriptor();
7679
final Object[] propertyValues =
7780
entityEntry.getStatus() == Status.DELETED
7881
? entityEntry.getDeletedState()
79-
: descriptor.getValues( entity );
82+
: descriptor.getValues( holder.getEntity() );
8083
final int[] dirty =
8184
descriptor.findDirty( propertyValues, entityEntry.getLoadedState(), entity, session );
8285
return dirty != null;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /