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 2ee7d1e

Browse files
committed
HHH-19605 Fix entity dirtiness logic when dealing with proxies
1 parent 5452f9e commit 2ee7d1e

File tree

2 files changed

+26
-51
lines changed

2 files changed

+26
-51
lines changed

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

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.io.Serializable;
1111

1212
import org.hibernate.AssertionFailure;
13-
import org.hibernate.CustomEntityDirtinessStrategy;
1413
import org.hibernate.HibernateException;
1514
import org.hibernate.LockMode;
1615
import org.hibernate.UnsupportedLockAttemptException;
@@ -21,7 +20,6 @@
2120
import org.hibernate.engine.spi.EntityKey;
2221
import org.hibernate.engine.spi.ManagedEntity;
2322
import org.hibernate.engine.spi.PersistenceContext;
24-
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
2523
import org.hibernate.engine.spi.SelfDirtinessTracker;
2624
import org.hibernate.engine.spi.SessionFactoryImplementor;
2725
import org.hibernate.engine.spi.SessionImplementor;
@@ -41,10 +39,8 @@
4139
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.PREVIOUS_STATUS;
4240
import static org.hibernate.engine.internal.EntityEntryImpl.EnumState.STATUS;
4341
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
44-
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
42+
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptableOrNull;
4543
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTracker;
46-
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
47-
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
4844
import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker;
4945
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfManagedEntity;
5046
import static org.hibernate.engine.internal.ManagedTypeHelper.processIfSelfDirtinessTracker;
@@ -56,7 +52,6 @@
5652
import static org.hibernate.engine.spi.Status.SAVING;
5753
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
5854
import static org.hibernate.pretty.MessageHelper.infoString;
59-
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
6055

6156
/**
6257
* A base implementation of {@link EntityEntry}.
@@ -390,46 +385,31 @@ private boolean isUnequivocallyNonDirty(Object entity) {
390385
}
391386

392387
private boolean isNonDirtyViaCustomStrategy(Object entity) {
393-
if ( isPersistentAttributeInterceptable( entity ) ) {
394-
finalPersistentAttributeInterceptorinterceptor =
395-
asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
396-
if ( interceptorinstanceofEnhancementAsProxyLazinessInterceptor ) {
388+
finalvarinterceptable = asPersistentAttributeInterceptableOrNull( entity );
389+
if ( interceptable != null ) {
390+
if ( interceptable.$$_hibernate_getInterceptor()instanceofEnhancementAsProxyLazinessInterceptorinterceptor
391+
&& !interceptor.isInitialized() ) {
397392
// we never have to check an uninitialized proxy
398393
return true;
399394
}
400395
}
401-
402-
final SessionImplementor session = (SessionImplementor) getPersistenceContext().getSession();
403-
final CustomEntityDirtinessStrategy customEntityDirtinessStrategy =
404-
session.getFactory().getCustomEntityDirtinessStrategy();
396+
final var session = (SessionImplementor) getPersistenceContext().getSession();
397+
final var customEntityDirtinessStrategy = session.getFactory().getCustomEntityDirtinessStrategy();
405398
return customEntityDirtinessStrategy.canDirtyCheck( entity, persister, session )
406399
&& !customEntityDirtinessStrategy.isDirty( entity, persister, session );
407400
}
408401

409402
private boolean isNonDirtyViaTracker(Object entity) {
410-
final boolean uninitializedProxy;
411-
if ( isPersistentAttributeInterceptable( entity ) ) {
412-
final PersistentAttributeInterceptor interceptor =
413-
asPersistentAttributeInterceptable( entity ).$$_hibernate_getInterceptor();
414-
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor lazinessInterceptor ) {
415-
return !lazinessInterceptor.hasWrittenFieldNames();
416-
}
417-
else {
418-
uninitializedProxy = false;
403+
final var interceptable = asPersistentAttributeInterceptableOrNull( entity );
404+
if ( interceptable != null ) {
405+
if ( interceptable.$$_hibernate_getInterceptor() instanceof EnhancementAsProxyLazinessInterceptor interceptor ) {
406+
return !interceptor.hasWrittenFieldNames();
419407
}
420408
}
421-
else if ( isHibernateProxy( entity ) ) {
422-
uninitializedProxy = extractLazyInitializer( entity ).isUninitialized();
423-
}
424-
else {
425-
uninitializedProxy = false;
426-
}
427-
// we never have to check an uninitialized proxy
428-
return uninitializedProxy
429-
|| !persister.hasCollections()
430-
&& !persister.hasMutableProperties()
431-
&& !asSelfDirtinessTracker( entity ).$$_hibernate_hasDirtyAttributes()
432-
&& asManagedEntity( entity ).$$_hibernate_useTracker();
409+
return !persister.hasCollections()
410+
&& !persister.hasMutableProperties()
411+
&& asManagedEntity( entity ).$$_hibernate_useTracker()
412+
&& !asSelfDirtinessTracker( entity ).$$_hibernate_hasDirtyAttributes();
433413
}
434414

435415
@Override

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

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +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;
12-
import org.hibernate.engine.spi.PersistenceContext;
1311
import org.hibernate.engine.spi.Status;
1412
import org.hibernate.event.spi.DirtyCheckEvent;
1513
import org.hibernate.event.spi.DirtyCheckEventListener;
@@ -38,15 +36,13 @@ public class DefaultDirtyCheckEventListener implements DirtyCheckEventListener {
3836

3937
@Override
4038
public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
41-
final EventSource session = event.getSession();
42-
final PersistenceContext persistenceContext = session.getPersistenceContext();
43-
final var holdersByKey = persistenceContext.getEntityHoldersByKey();
44-
if ( holdersByKey != null ) {
45-
for ( var entry : holdersByKey.entrySet() ) {
46-
if ( isEntityDirty( entry.getValue(), session ) ) {
47-
event.setDirty( true );
48-
return;
49-
}
39+
final var session = event.getSession();
40+
final var persistenceContext = session.getPersistenceContext();
41+
final var entityEntries = persistenceContext.reentrantSafeEntityEntries();
42+
for ( var me : entityEntries ) {
43+
if ( isEntityDirty( me.getKey(), me.getValue(), session ) ) {
44+
event.setDirty( true );
45+
return;
5046
}
5147
}
5248
final var entriesByCollection = persistenceContext.getCollectionEntries();
@@ -60,20 +56,19 @@ public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
6056
}
6157
}
6258

63-
private static boolean isEntityDirty(EntityHolder holder, EventSource session) {
64-
final EntityEntry entityEntry = holder.getEntityEntry();
59+
private static boolean isEntityDirty(Object entity, EntityEntry entityEntry, EventSource session) {
6560
final Status status = entityEntry.getStatus();
6661
return switch ( status ) {
6762
case GONE, READ_ONLY -> false;
6863
case DELETED -> true;
69-
case MANAGED -> isManagedEntityDirty( holder.getManagedObject(), holder.getDescriptor(), entityEntry, session );
64+
case MANAGED -> isManagedEntityDirty( entity, entityEntry, session );
7065
case SAVING, LOADING -> throw new AssertionFailure( "Unexpected status: " + status );
7166
};
7267
}
7368

74-
private static boolean isManagedEntityDirty(
75-
Object entity, EntityPersister descriptor, EntityEntry entityEntry, EventSource session) {
69+
private static boolean isManagedEntityDirty(Object entity, EntityEntry entityEntry, EventSource session) {
7670
if ( entityEntry.requiresDirtyCheck( entity ) ) { // takes into account CustomEntityDirtinessStrategy
71+
final EntityPersister descriptor = entityEntry.getPersister();
7772
final Object[] propertyValues =
7873
entityEntry.getStatus() == Status.DELETED
7974
? entityEntry.getDeletedState()

0 commit comments

Comments
(0)

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