HHH-18713 saveOrUpdate changed behaviour with bytecode enhancer

This commit is contained in:
Andrea Boriero 2024-10-10 16:25:35 +02:00 committed by Andrea Boriero
parent b26441aee8
commit cef03a3256
2 changed files with 35 additions and 9 deletions

View File

@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor; import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
@ -19,6 +20,7 @@ import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.CollectionEntry; import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.hibernate.event.spi.DeleteContext; import org.hibernate.event.spi.DeleteContext;
@ -27,8 +29,6 @@ import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
@ -38,13 +38,13 @@ import org.hibernate.type.EntityType;
import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.ManyToOneType; import org.hibernate.type.ManyToOneType;
import org.hibernate.type.OneToOneType; import org.hibernate.type.OneToOneType;
import org.hibernate.type.OneToOneType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.internal.ManagedTypeHelper.asManagedEntity;
import static org.hibernate.engine.internal.ManagedTypeHelper.asSelfDirtinessTrackerOrNull;
import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy; import static org.hibernate.engine.internal.ManagedTypeHelper.isHibernateProxy;
import static org.hibernate.engine.spi.CascadingActions.CHECK_ON_FLUSH; import static org.hibernate.engine.spi.CascadingActions.CHECK_ON_FLUSH;
import static org.hibernate.pretty.MessageHelper.infoString; import static org.hibernate.pretty.MessageHelper.infoString;
import static org.hibernate.type.ForeignKeyDirection.TO_PARENT;
/** /**
* Delegate responsible for, in conjunction with the various * Delegate responsible for, in conjunction with the various
@ -97,15 +97,29 @@ public final class Cascade {
final PersistenceContext persistenceContext = eventSource.getPersistenceContextInternal(); final PersistenceContext persistenceContext = eventSource.getPersistenceContextInternal();
final boolean enhancedForLazyLoading = persister.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading(); final boolean enhancedForLazyLoading = persister.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
final EntityEntry entry; final EntityEntry entry;
final Set<String> dirtyAttributes;
if ( enhancedForLazyLoading ) { if ( enhancedForLazyLoading ) {
entry = persistenceContext.getEntry( parent ); entry = persistenceContext.getEntry( parent );
if ( entry != null if ( entry != null && entry.getLoadedState() == null && entry.getStatus() == Status.MANAGED ) {
&& entry.getLoadedState() == null final SelfDirtinessTracker selfDirtinessTracker = asSelfDirtinessTrackerOrNull( parent );
&& entry.getStatus() == Status.MANAGED ) { if ( selfDirtinessTracker == null ) {
return; return;
}
else {
if ( asManagedEntity( parent ).$$_hibernate_useTracker() ) {
dirtyAttributes = Set.of( selfDirtinessTracker.$$_hibernate_getDirtyAttributes() );
}
else {
dirtyAttributes = null;
}
}
}
else {
dirtyAttributes = null;
} }
} }
else { else {
dirtyAttributes = null;
entry = null; entry = null;
} }
final Type[] types = persister.getPropertyTypes(); final Type[] types = persister.getPropertyTypes();
@ -114,8 +128,11 @@ public final class Cascade {
final boolean hasUninitializedLazyProperties = persister.hasUninitializedLazyProperties( parent ); final boolean hasUninitializedLazyProperties = persister.hasUninitializedLazyProperties( parent );
for ( int i = 0; i < types.length; i++) { for ( int i = 0; i < types.length; i++) {
final CascadeStyle style = cascadeStyles[ i ];
final String propertyName = propertyNames[ i ]; final String propertyName = propertyNames[ i ];
if ( dirtyAttributes != null && !dirtyAttributes.contains( propertyName ) ) {
return;
}
final CascadeStyle style = cascadeStyles[ i ];
final Type type = types[i]; final Type type = types[i];
final boolean isUninitializedProperty = final boolean isUninitializedProperty =
hasUninitializedLazyProperties && hasUninitializedLazyProperties &&

View File

@ -390,6 +390,15 @@ public final class ManagedTypeHelper {
throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to SelfDirtinessTracker" ); throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to SelfDirtinessTracker" );
} }
public static SelfDirtinessTracker asSelfDirtinessTrackerOrNull(final Object entity) {
Objects.requireNonNull( entity );
if ( entity instanceof PrimeAmongSecondarySupertypes ) {
PrimeAmongSecondarySupertypes t = (PrimeAmongSecondarySupertypes) entity;
return t.asSelfDirtinessTracker();
}
return null;
}
/** /**
* Cast the object to an HibernateProxy, or return null in case it is not an instance of HibernateProxy * Cast the object to an HibernateProxy, or return null in case it is not an instance of HibernateProxy
* @param entity the entity to cast * @param entity the entity to cast