HHH-14424 When enhanced as a proxy is enabled with dirty checking, on flush uninitialized entities containing collections are updated and all the fields are set to null
This commit is contained in:
parent
26a46b2010
commit
cfc7b97250
|
@ -35,6 +35,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
|
||||
private final boolean inLineDirtyChecking;
|
||||
private Set<String> writtenFieldNames;
|
||||
private Set<String> collectionAttributeNames;
|
||||
|
||||
private Status status;
|
||||
|
||||
|
@ -57,11 +58,22 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
this.entityKey = entityKey;
|
||||
|
||||
final EntityPersister entityPersister = session.getFactory().getMetamodel().entityPersister( entityName );
|
||||
if ( entityPersister.hasCollections() ) {
|
||||
Type[] propertyTypes = entityPersister.getPropertyTypes();
|
||||
collectionAttributeNames = new HashSet<>();
|
||||
for ( int i = 0; i < propertyTypes.length; i++ ) {
|
||||
Type propertyType = propertyTypes[i];
|
||||
if ( propertyType.isCollectionType() ) {
|
||||
collectionAttributeNames.add( entityPersister.getPropertyNames()[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.inLineDirtyChecking = entityPersister.getEntityMode() == EntityMode.POJO
|
||||
&& SelfDirtinessTracker.class.isAssignableFrom( entityPersister.getMappedClass() );
|
||||
// if self-dirty tracking is enabled but DynamicUpdate is not enabled then we need to initialise the entity
|
||||
// because the pre-computed update statement contains even not dirty properties and so we need all the values
|
||||
initializeBeforeWrite = !inLineDirtyChecking || !entityPersister.getEntityMetamodel().isDynamicUpdate();
|
||||
initializeBeforeWrite = !( inLineDirtyChecking && entityPersister.getEntityMetamodel().isDynamicUpdate() );
|
||||
status = Status.UNINITIALIZED;
|
||||
}
|
||||
|
||||
|
@ -245,7 +257,8 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
return newValue;
|
||||
}
|
||||
|
||||
if ( initializeBeforeWrite ) {
|
||||
if ( initializeBeforeWrite
|
||||
|| ( collectionAttributeNames != null && collectionAttributeNames.contains( attributeName ) ) ) {
|
||||
// we need to force-initialize the proxy - the fetch group to which the `attributeName` belongs
|
||||
try {
|
||||
forceInitialize( target, attributeName );
|
||||
|
@ -267,6 +280,8 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
writtenFieldNames = new HashSet<>();
|
||||
}
|
||||
writtenFieldNames.add( attributeName );
|
||||
|
||||
( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName );
|
||||
}
|
||||
|
||||
return newValue;
|
||||
|
@ -323,6 +338,10 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
|
|||
status = Status.INITIALIZED;
|
||||
}
|
||||
|
||||
public boolean hasWrittenFieldNames() {
|
||||
return writtenFieldNames != null && writtenFieldNames.size() != 0;
|
||||
}
|
||||
|
||||
private enum Status {
|
||||
UNINITIALIZED,
|
||||
INITIALIZING,
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.engine.internal;
|
|||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||
|
@ -353,8 +352,12 @@ public abstract class AbstractEntityEntry implements Serializable, EntityEntry {
|
|||
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
|
||||
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
|
||||
EnhancementAsProxyLazinessInterceptor enhancementAsProxyLazinessInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
|
||||
if ( enhancementAsProxyLazinessInterceptor.hasWrittenFieldNames() ) {
|
||||
return false;
|
||||
}
|
||||
// When a proxy has dirty attributes, we have to treat it like a normal entity to flush changes
|
||||
uninitializedProxy = !enhancementAsProxyLazinessInterceptor.isInitialized() && !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
|
||||
return !enhancementAsProxyLazinessInterceptor.isInitialized()
|
||||
|| !persister.hasCollections() && !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
|
||||
}
|
||||
}
|
||||
else if ( entity instanceof HibernateProxy ) {
|
||||
|
|
Loading…
Reference in New Issue