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 1eae89d

Browse files
committed
HHH-19605 Fix entity dirtiness logic when dealing with proxies
1 parent b11f5ce commit 1eae89d

File tree

2 files changed

+23
-41
lines changed

2 files changed

+23
-41
lines changed

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

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@
3737
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.PREVIOUS_STATUS;
3838
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.STATUS;
3939
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
40-
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
40+
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptableOrNull;
4141
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;
4442
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker;
4543
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfManagedEntity;
4644
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirtinessTracker;
@@ -52,7 +50,6 @@
5250
import static org.hibernate.engine.spi.Status.SAVING;
5351
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
5452
import static org.hibernate.pretty.MessageHelper.infoString;
55-
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
5653

5754
/**
5855
* A base implementation of {@link EntityEntry}.
@@ -385,43 +382,31 @@ private boolean isUnequivocallyNonDirty(Object entity) {
385382
}
386383

387384
private boolean isNonDirtyViaCustomStrategy(Object entity) {
388-
if ( isPersistentAttributeInterceptable( entity ) ) {
389-
if ( asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor()
390-
instanceof EnhancementAsProxyLazinessInterceptor ) {
385+
final var interceptable = asPersistentAttributeInterceptableOrNull( entity );
386+
if ( interceptable != null ) {
387+
if ( interceptable.$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor interceptor
388+
&& !interceptor.isInitialized() ) {
391389
// we never have to check an uninitialized proxy
392390
return true;
393391
}
394392
}
395-
396393
final var session = (SessionImplementor) getPersistenceContext().getSession();
397394
final var customEntityDirtinessStrategy = session.getFactory().getCustomEntityDirtinessStrategy();
398395
return customEntityDirtinessStrategy.canDirtyCheck( entity, persister, session )
399396
&& !customEntityDirtinessStrategy.isDirty( entity, persister, session );
400397
}
401398

402399
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;
400+
final var interceptable = asPersistentAttributeInterceptableOrNull( entity );
401+
if ( interceptable != null ) {
402+
if ( interceptable.$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor interceptor ) {
403+
return !interceptor.hasWrittenFieldNames();
411404
}
412405
}
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();
406+
return !persister.hasCollections()
407+
&& !persister.hasMutableProperties()
408+
&& asManagedEntity( entity ).$$_hibernate_useTracker()
409+
&& !asSelfDirtinessTracker( entity ).$$_hibernate_hasDirtyAttributes();
425410
}
426411

427412
@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 によって変換されたページ (->オリジナル) /