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 0fe6273

Browse files
committed
HHH-19605 Fix entity dirtiness logic when dealing with proxies
1 parent c50b13d commit 0fe6273

File tree

2 files changed

+24
-41
lines changed

2 files changed

+24
-41
lines changed

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

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.hibernate.engine.spi.Status;
2727
import org.hibernate.internal.util.ImmutableBitSet;
2828
import org.hibernate.persister.entity.EntityPersister;
29+
import org.hibernate.proxy.HibernateProxy;
2930
import org.hibernate.type.TypeHelper;
3031

3132
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -37,10 +38,8 @@
3738
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.PREVIOUS_STATUS;
3839
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.STATUS;
3940
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
40-
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
41+
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptableOrNull;
4142
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;
4443
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker;
4544
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfManagedEntity;
4645
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirtinessTracker;
@@ -52,7 +51,6 @@
5251
import static org.hibernate.engine.spi.Status.SAVING;
5352
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
5453
import static org.hibernate.pretty.MessageHelper.infoString;
55-
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
5654

5755
/**
5856
* A base implementation of {@link EntityEntry}.
@@ -385,43 +383,31 @@ private boolean isUnequivocallyNonDirty(Object entity) {
385383
}
386384

387385
private boolean isNonDirtyViaCustomStrategy(Object entity) {
388-
if ( isPersistentAttributeInterceptable( entity ) ) {
389-
if ( asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor()
390-
instanceof EnhancementAsProxyLazinessInterceptor ) {
386+
final var interceptable = asPersistentAttributeInterceptableOrNull( entity );
387+
if ( interceptable != null ) {
388+
if ( interceptable.$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor interceptor
389+
&& !interceptor.isInitialized() ) {
391390
// we never have to check an uninitialized proxy
392391
return true;
393392
}
394393
}
395-
396394
final var session = (SessionImplementor) getPersistenceContext().getSession();
397395
final var customEntityDirtinessStrategy = session.getFactory().getCustomEntityDirtinessStrategy();
398396
return customEntityDirtinessStrategy.canDirtyCheck( entity, persister, session )
399397
&& !customEntityDirtinessStrategy.isDirty( entity, persister, session );
400398
}
401399

402400
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();
408-
}
409-
else {
410-
uninitializedProxy = false;
401+
final var interceptable = asPersistentAttributeInterceptableOrNull( entity );
402+
if ( interceptable != null ) {
403+
if ( interceptable.$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor interceptor ) {
404+
return !interceptor.hasWrittenFieldNames();
411405
}
412406
}
413-
else if ( isHibernateProxy( entity ) ) {
414-
uninitializedProxy = extractLazyInitializer( entity ).isUninitialized();
415-
}
416-
else {
417-
uninitializedProxy = false;
418-
}
419-
// 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();
407+
return !persister.hasCollections()
408+
&& !persister.hasMutableProperties()
409+
&& asManagedEntity( entity ).$$_hibernate_useTracker()
410+
&& !asSelfDirtinessTracker( entity ).$$_hibernate_hasDirtyAttributes();
425411
}
426412

427413
@Override

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

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import org.hibernate.HibernateException;
99
import org.hibernate.collection.spi.PersistentCollection;
1010
import org.hibernate.engine.spi.EntityEntry;
11-
import org.hibernate.engine.spi.EntityHolder;
1211
import org.hibernate.engine.spi.Status;
1312
import org.hibernate.event.spi.DirtyCheckEvent;
1413
import org.hibernate.event.spi.DirtyCheckEventListener;
@@ -17,6 +16,7 @@
1716
import org.hibernate.persister.entity.EntityPersister;
1817

1918

19+
2020
/**
2121
* Determines if the current session holds modified state which
2222
* would be synchronized with the database if the session were
@@ -39,13 +39,11 @@ public class DefaultDirtyCheckEventListener implements DirtyCheckEventListener {
3939
public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
4040
final var session = event.getSession();
4141
final var persistenceContext = session.getPersistenceContext();
42-
final var holdersByKey = persistenceContext.getEntityHoldersByKey();
43-
if ( holdersByKey != null ) {
44-
for ( var entry : holdersByKey.entrySet() ) {
45-
if ( isEntityDirty( entry.getValue(), session ) ) {
46-
event.setDirty( true );
47-
return;
48-
}
42+
final var entityEntries = persistenceContext.reentrantSafeEntityEntries();
43+
for ( var me : entityEntries ) {
44+
if ( isEntityDirty( me.getKey(), me.getValue(), session ) ) {
45+
event.setDirty( true );
46+
return;
4947
}
5048
}
5149
final var entriesByCollection = persistenceContext.getCollectionEntries();
@@ -59,20 +57,19 @@ public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
5957
}
6058
}
6159

62-
private static boolean isEntityDirty(EntityHolder holder, EventSource session) {
63-
final var entityEntry = holder.getEntityEntry();
60+
private static boolean isEntityDirty(Object entity, EntityEntry entityEntry, EventSource session) {
6461
final Status status = entityEntry.getStatus();
6562
return switch ( status ) {
6663
case GONE, READ_ONLY -> false;
6764
case DELETED -> true;
68-
case MANAGED -> isManagedEntityDirty( holder.getManagedObject(), holder.getDescriptor(), entityEntry, session );
65+
case MANAGED -> isManagedEntityDirty( entity, entityEntry, session );
6966
case SAVING, LOADING -> throw new AssertionFailure( "Unexpected status: " + status );
7067
};
7168
}
7269

73-
private static boolean isManagedEntityDirty(
74-
Object entity, EntityPersister descriptor, EntityEntry entityEntry, EventSource session) {
70+
private static boolean isManagedEntityDirty(Object entity, EntityEntry entityEntry, EventSource session) {
7571
if ( entityEntry.requiresDirtyCheck( entity ) ) { // takes into account CustomEntityDirtinessStrategy
72+
final EntityPersister descriptor = entityEntry.getPersister();
7673
final Object[] propertyValues =
7774
entityEntry.getStatus() == Status.DELETED
7875
? entityEntry.getDeletedState()

0 commit comments

Comments
(0)

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