From 96c3a8b6b2d77882ddc69e0ae61ccba5e9b1cd97 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Fri, 4 Oct 2019 16:41:07 +0100 Subject: [PATCH] HHH-13653 Uninitialized entity does not get initialized when a setter is called with enhancement-as-proxy enabled (cherry picked from commit 3c1f4356dd3a6e6d88ee4a9442119f262b6dfb97) --- .../EnhancementAsProxyLazinessInterceptor.java | 14 +++++++++++--- .../lazy/proxy/ProxyInitializeAndUpdateTest.java | 1 - ...eTestWithLazyLoadingAndInlineDirtyTracking.java | 12 ++++++------ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/EnhancementAsProxyLazinessInterceptor.java b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/EnhancementAsProxyLazinessInterceptor.java index 653f4604aa..697f79a1d4 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/EnhancementAsProxyLazinessInterceptor.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/enhance/spi/interceptor/EnhancementAsProxyLazinessInterceptor.java @@ -6,7 +6,6 @@ */ package org.hibernate.bytecode.enhance.spi.interceptor; -import java.io.Serializable; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -40,6 +39,8 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter private boolean initialized; + private boolean initializeBeforeWrite; + public EnhancementAsProxyLazinessInterceptor( String entityName, Set identifierAttributeNames, @@ -59,6 +60,9 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter final EntityPersister entityPersister = session.getFactory().getMetamodel().entityPersister( entityName ); 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(); } public EntityKey getEntityKey() { @@ -89,7 +93,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter .entityPersister( getEntityName() ); final EntityTuplizer entityTuplizer = entityPersister.getEntityTuplizer(); - if ( inLineDirtyChecking && writtenFieldNames != null && !writtenFieldNames.isEmpty() ) { + if ( writtenFieldNames != null && !writtenFieldNames.isEmpty() ) { // enhancement has dirty-tracking available and at least one attribute was explicitly set @@ -241,7 +245,7 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter return newValue; } - if ( ! inLineDirtyChecking ) { + if ( initializeBeforeWrite ) { // we need to force-initialize the proxy - the fetch group to which the `attributeName` belongs try { forceInitialize( target, attributeName ); @@ -249,6 +253,10 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter finally { initialized = true; } + + if ( inLineDirtyChecking ) { + ( (SelfDirtinessTracker) target ).$$_hibernate_trackChange( attributeName ); + } } else { // because of the entity being enhanced with `org.hibernate.engine.spi.SelfDirtinessTracker` diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/ProxyInitializeAndUpdateTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/ProxyInitializeAndUpdateTest.java index 17e523867a..bfafecb138 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/ProxyInitializeAndUpdateTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/ProxyInitializeAndUpdateTest.java @@ -91,7 +91,6 @@ public class ProxyInitializeAndUpdateTest extends BaseNonConfigCoreFunctionalTes } @Test - @FailureExpected( jiraKey = "HHH-13653") public void testInitializeWithSetter() { inTransaction( session -> { diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking.java index 15b49622e0..3b0de35da4 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/proxy/SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking.java @@ -115,13 +115,13 @@ public class SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking extends BaseN MatcherAssert.assertThat( interceptor, instanceOf( EnhancementAsProxyLazinessInterceptor.class ) ); loadedChild.setName( updatedName ); - assertEquals( 0, stats.getPrepareStatementCount() ); + assertEquals( 1, stats.getPrepareStatementCount() ); assertThat( loadedChild.getName(), is( updatedName ) ); - assertEquals( 0, stats.getPrepareStatementCount() ); + assertEquals( 1, stats.getPrepareStatementCount() ); } ); // the UPDATE - assertEquals( 1, stats.getPrepareStatementCount() ); + assertEquals( 2, stats.getPrepareStatementCount() ); doInHibernate( this::sessionFactory, s -> { Child loadedChild = s.load( Child.class, lastChildID ); @@ -143,11 +143,11 @@ public class SimpleUpdateTestWithLazyLoadingAndInlineDirtyTracking extends BaseN Parent parent = new Parent(); parent.setName( parentName ); - assertEquals( 0, stats.getPrepareStatementCount() ); + assertEquals( 1, stats.getPrepareStatementCount() ); loadedChild.setParent( parent ); - assertEquals( 0, stats.getPrepareStatementCount() ); + assertEquals( 1, stats.getPrepareStatementCount() ); assertThat( loadedChild.getParent().getName(), is( parentName ) ); - assertEquals( 0, stats.getPrepareStatementCount() ); + assertEquals( 1, stats.getPrepareStatementCount() ); s.save( parent ); } );