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 4a796dd

Browse files
committed
HHH-19605 Fix entity dirtiness logic when dealing with proxies
1 parent 02feed0 commit 4a796dd

File tree

2 files changed

+31
-50
lines changed

2 files changed

+31
-50
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: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,11 @@
99
import org.hibernate.collection.spi.PersistentCollection;
1010
import org.hibernate.engine.spi.EntityEntry;
1111
import org.hibernate.engine.spi.EntityHolder;
12-
import org.hibernate.engine.spi.PersistenceContext;
1312
import org.hibernate.engine.spi.Status;
1413
import org.hibernate.event.spi.DirtyCheckEvent;
1514
import org.hibernate.event.spi.DirtyCheckEventListener;
1615
import org.hibernate.event.spi.EventSource;
1716
import org.hibernate.persister.collection.CollectionPersister;
18-
import org.hibernate.persister.entity.EntityPersister;
19-
2017

2118
/**
2219
* Determines if the current session holds modified state which
@@ -38,12 +35,12 @@ public class DefaultDirtyCheckEventListener implements DirtyCheckEventListener {
3835

3936
@Override
4037
public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
41-
final EventSource session = event.getSession();
42-
final PersistenceContext persistenceContext = session.getPersistenceContext();
38+
final var session = event.getSession();
39+
final var persistenceContext = session.getPersistenceContextInternal();
4340
final var holdersByKey = persistenceContext.getEntityHoldersByKey();
4441
if ( holdersByKey != null ) {
45-
for ( var entry : holdersByKey.entrySet() ) {
46-
if ( isEntityDirty( entry.getValue(), session ) ) {
42+
for ( var holder : holdersByKey.values() ) {
43+
if ( isEntityDirty( holder, session ) ) {
4744
event.setDirty( true );
4845
return;
4946
}
@@ -61,25 +58,29 @@ public void onDirtyCheck(DirtyCheckEvent event) throws HibernateException {
6158
}
6259

6360
private static boolean isEntityDirty(EntityHolder holder, EventSource session) {
64-
final EntityEntry entityEntry = holder.getEntityEntry();
61+
final var entityEntry = holder.getEntityEntry();
62+
if ( entityEntry == null ) {
63+
// holders with no entity entry yet cannot contain dirty entities
64+
return false;
65+
}
6566
final Status status = entityEntry.getStatus();
6667
return switch ( status ) {
6768
case GONE, READ_ONLY -> false;
6869
case DELETED -> true;
69-
case MANAGED -> isManagedEntityDirty( holder.getManagedObject(), holder.getDescriptor(), entityEntry, session );
70+
case MANAGED -> isManagedEntityDirty( holder.getEntity(), entityEntry, session );
7071
case SAVING, LOADING -> throw new AssertionFailure( "Unexpected status: " + status );
7172
};
7273
}
7374

74-
private static boolean isManagedEntityDirty(
75-
Object entity, EntityPersister descriptor, EntityEntry entityEntry, EventSource session) {
75+
private static boolean isManagedEntityDirty(Object entity, EntityEntry entityEntry, EventSource session) {
7676
if ( entityEntry.requiresDirtyCheck( entity ) ) { // takes into account CustomEntityDirtinessStrategy
77-
final Object[] propertyValues =
77+
final var persister = entityEntry.getPersister();
78+
final var propertyValues =
7879
entityEntry.getStatus() == Status.DELETED
7980
? entityEntry.getDeletedState()
80-
: descriptor.getValues( entity );
81-
final int[] dirty =
82-
descriptor.findDirty( propertyValues, entityEntry.getLoadedState(), entity, session );
81+
: persister.getValues( entity );
82+
final var dirty =
83+
persister.findDirty( propertyValues, entityEntry.getLoadedState(), entity, session );
8384
return dirty != null;
8485
}
8586
else {

0 commit comments

Comments
(0)

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