Skip to content

Commit cfc7b97

Browse files
committed
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
1 parent 26a46b2 commit cfc7b97

File tree

3 files changed

+26
-4
lines changed

3 files changed

+26
-4
lines changed

hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/EnhancementAsProxyLazinessInterceptor.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
3535

3636
private final boolean inLineDirtyChecking;
3737
private Set<String> writtenFieldNames;
38+
private Set<String> collectionAttributeNames;
3839

3940
private Status status;
4041

@@ -57,11 +58,22 @@ public EnhancementAsProxyLazinessInterceptor(
5758
this.entityKey = entityKey;
5859

5960
final EntityPersister entityPersister = session.getFactory().getMetamodel().entityPersister( entityName );
61+
if ( entityPersister.hasCollections() ) {
62+
Type[] propertyTypes = entityPersister.getPropertyTypes();
63+
collectionAttributeNames = new HashSet<>();
64+
for ( int i = 0; i < propertyTypes.length; i++ ) {
65+
Type propertyType = propertyTypes[i];
66+
if ( propertyType.isCollectionType() ) {
67+
collectionAttributeNames.add( entityPersister.getPropertyNames()[i] );
68+
}
69+
}
70+
}
71+
6072
this.inLineDirtyChecking = entityPersister.getEntityMode() == EntityMode.POJO
6173
&& SelfDirtinessTracker.class.isAssignableFrom( entityPersister.getMappedClass() );
6274
// if self-dirty tracking is enabled but DynamicUpdate is not enabled then we need to initialise the entity
6375
// because the pre-computed update statement contains even not dirty properties and so we need all the values
64-
initializeBeforeWrite = !inLineDirtyChecking || !entityPersister.getEntityMetamodel().isDynamicUpdate();
76+
initializeBeforeWrite = !( inLineDirtyChecking && entityPersister.getEntityMetamodel().isDynamicUpdate() );
6577
status = Status.UNINITIALIZED;
6678
}
6779

@@ -245,7 +257,8 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
245257
return newValue;
246258
}
247259

248-
if ( initializeBeforeWrite ) {
260+
if ( initializeBeforeWrite
261+
|| ( collectionAttributeNames != null && collectionAttributeNames.contains( attributeName ) ) ) {
249262
// we need to force-initialize the proxy - the fetch group to which the `attributeName` belongs
250263
try {
251264
forceInitialize( target, attributeName );
@@ -267,6 +280,8 @@ protected Object handleWrite(Object target, String attributeName, Object oldValu
267280
writtenFieldNames = new HashSet<>();
268281
}
269282
writtenFieldNames.add( attributeName );
283+
284+
( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName );
270285
}
271286

272287
return newValue;
@@ -323,6 +338,10 @@ private void setInitialized() {
323338
status = Status.INITIALIZED;
324339
}
325340

341+
public boolean hasWrittenFieldNames() {
342+
return writtenFieldNames != null && writtenFieldNames.size() != 0;
343+
}
344+
326345
private enum Status {
327346
UNINITIALIZED,
328347
INITIALIZING,

hibernate-core/src/main/java/org/hibernate/engine/internal/AbstractEntityEntry.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import java.io.IOException;
1010
import java.io.ObjectOutputStream;
1111
import java.io.Serializable;
12-
import java.util.function.Supplier;
1312

1413
import org.hibernate.AssertionFailure;
1514
import org.hibernate.CustomEntityDirtinessStrategy;
@@ -353,8 +352,12 @@ private boolean isUnequivocallyNonDirty(Object entity) {
353352
final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor();
354353
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) {
355354
EnhancementAsProxyLazinessInterceptor enhancementAsProxyLazinessInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor;
355+
if ( enhancementAsProxyLazinessInterceptor.hasWrittenFieldNames() ) {
356+
return false;
357+
}
356358
// When a proxy has dirty attributes, we have to treat it like a normal entity to flush changes
357-
uninitializedProxy = !enhancementAsProxyLazinessInterceptor.isInitialized() && !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
359+
return !enhancementAsProxyLazinessInterceptor.isInitialized()
360+
|| !persister.hasCollections() && !( (SelfDirtinessTracker) entity ).$$_hibernate_hasDirtyAttributes();
358361
}
359362
}
360363
else if ( entity instanceof HibernateProxy ) {

0 commit comments

Comments
 (0)