Skip to content

Commit

Permalink
HHH-14424 When enhanced as a proxy is enabled with dirty checking, on…
Browse files Browse the repository at this point in the history
… flush uninitialized entities containing collections are updated and all the fields are set to null
  • Loading branch information
dreab8 authored and Sanne committed Feb 8, 2021
1 parent fa00401 commit c379110
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 4 deletions.
Expand Up @@ -35,6 +35,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter

private final boolean inLineDirtyChecking;
private Set<String> writtenFieldNames;
private Set<String> collectionAttributeNames;

private Status status;

Expand All @@ -57,11 +58,22 @@ public EnhancementAsProxyLazinessInterceptor(
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;
}

Expand Down Expand Up @@ -245,7 +257,8 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
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 );
Expand All @@ -267,6 +280,8 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
writtenFieldNames = new HashSet<>();
}
writtenFieldNames.add( attributeName );

( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName );
}

return newValue;
Expand Down Expand Up @@ -323,6 +338,10 @@ private void setInitialized() {
status = Status.INITIALIZED;
}

public boolean hasWrittenFieldNames() {
return writtenFieldNames != null && writtenFieldNames.size() != 0;
}

private enum Status {
UNINITIALIZED,
INITIALIZING,
Expand Down
Expand Up @@ -9,7 +9,6 @@
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;
Expand Down Expand Up @@ -353,8 +352,12 @@ private boolean isUnequivocallyNonDirty(Object entity) {
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 ) {
Expand Down

0 comments on commit c379110

Please sign in to comment.