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

Browse files
committed
HHH-19605 Fix entity dirtiness logic when dealing with proxies
1 parent ee6e7b3 commit 2cfe7da

File tree

2 files changed

+27
-40
lines changed

2 files changed

+27
-40
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: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
import org.hibernate.event.spi.DirtyCheckEventListener;
1515
import org.hibernate.event.spi.EventSource;
1616
import org.hibernate.persister.collection.CollectionPersister;
17-
import org.hibernate.persister.entity.EntityPersister;
18-
1917

2018
/**
2119
* Determines if the current session holds modified state which
@@ -38,11 +36,11 @@ public class DefaultDirtyCheckEventListener implements DirtyCheckEventListener {
3836
@Override
3937
public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
4038
final var session = event.getSession();
41-
final var persistenceContext = session.getPersistenceContext();
39+
final var persistenceContext = session.getPersistenceContextInternal();
4240
final var holdersByKey = persistenceContext.getEntityHoldersByKey();
4341
if ( holdersByKey != null ) {
44-
for ( var entry : holdersByKey.entrySet() ) {
45-
if ( isEntityDirty( entry.getValue(), session ) ) {
42+
for ( var holder : holdersByKey.values() ) {
43+
if ( isEntityDirty( holder, session ) ) {
4644
event.setDirty( true );
4745
return;
4846
}
@@ -61,24 +59,28 @@ public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
6159

6260
private static boolean isEntityDirty(EntityHolder holder, EventSource session) {
6361
final var entityEntry = holder.getEntityEntry();
62+
if ( entityEntry == null ) {
63+
// holders with no entity entry yet cannot contain dirty entities
64+
return false;
65+
}
6466
final Status status = 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.getEntity(), 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+
private static boolean isManagedEntityDirty(Object entity, EntityEntry entityEntry, EventSource session) {
7576
if ( entityEntry.requiresDirtyCheck( entity ) ) { // takes into account CustomEntityDirtinessStrategy
76-
final Object[] propertyValues =
77+
final var persister = entityEntry.getPersister();
78+
final var propertyValues =
7779
entityEntry.getStatus() == Status.DELETED
7880
? entityEntry.getDeletedState()
79-
: descriptor.getValues( entity );
80-
final int[] dirty =
81-
descriptor.findDirty( propertyValues, entityEntry.getLoadedState(), entity, session );
81+
: persister.getValues( entity );
82+
final var dirty =
83+
persister.findDirty( propertyValues, entityEntry.getLoadedState(), entity, session );
8284
return dirty != null;
8385
}
8486
else {

0 commit comments

Comments
(0)

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