HHH-13653 Uninitialized entity does not get initialized when a setter is called with enhancement-as-proxy enabled

(cherry picked from commit 3c1f4356dd)
This commit is contained in:
Andrea Boriero 2019-10-04 16:41:07 +01:00 committed by Gail Badner
parent 469559c403
commit 96c3a8b6b2
3 changed files with 17 additions and 10 deletions

View File

@ -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<String> 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`

View File

@ -91,7 +91,6 @@ public class ProxyInitializeAndUpdateTest extends BaseNonConfigCoreFunctionalTes
}
@Test
@FailureExpected( jiraKey = "HHH-13653")
public void testInitializeWithSetter() {
inTransaction(
session -> {

View File

@ -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 );
} );