HHH-9806 Backport fix for bytecode enhancement dirty tracking not working when PersistentAttributeInterceptor is not injected

This commit is contained in:
barreiro 2015-05-21 16:28:37 +01:00
parent d9495474ef
commit bc382dde74
2 changed files with 39 additions and 46 deletions

View File

@ -23,20 +23,6 @@
*/ */
package org.hibernate.bytecode.enhance.spi; package org.hibernate.bytecode.enhance.spi;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import javassist.CannotCompileException; import javassist.CannotCompileException;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
@ -58,7 +44,6 @@ import javassist.bytecode.SignatureAttribute;
import javassist.bytecode.StackMapTable; import javassist.bytecode.StackMapTable;
import javassist.bytecode.annotation.Annotation; import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.stackmap.MapMaker; import javassist.bytecode.stackmap.MapMaker;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.bytecode.enhance.EnhancementException; import org.hibernate.bytecode.enhance.EnhancementException;
import org.hibernate.engine.spi.EntityEntry; import org.hibernate.engine.spi.EntityEntry;
@ -70,6 +55,20 @@ import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
/** /**
* Class responsible for performing enhancement. * Class responsible for performing enhancement.
* *
@ -660,7 +659,7 @@ public class Enhancer {
private void createCollectionDirtyCheckMethod(CtClass managedCtClass) throws CannotCompileException { private void createCollectionDirtyCheckMethod(CtClass managedCtClass) throws CannotCompileException {
StringBuilder builder = new StringBuilder( "private boolean " ) StringBuilder builder = new StringBuilder( "private boolean " )
.append( EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME ) .append( EnhancerConstants.TRACKER_COLLECTION_CHANGED_NAME )
.append( "() { if ($$_hibernate_getInterceptor() == null || " ) .append( "() { if (" )
.append( EnhancerConstants.TRACKER_COLLECTION_NAME ) .append( EnhancerConstants.TRACKER_COLLECTION_NAME )
.append( " == null) return false; " ); .append( " == null) return false; " );
@ -1157,10 +1156,9 @@ public class Enhancer {
private String entityMethodBody(CtField currentValue) { private String entityMethodBody(CtField currentValue) {
StringBuilder inlineBuilder = new StringBuilder(); StringBuilder inlineBuilder = new StringBuilder();
try { try {
inlineBuilder.append( "if ( $$_hibernate_getInterceptor() != null " );
//primitives || enums //primitives || enums
if ( currentValue.getType().isPrimitive() || currentValue.getType().isEnum() ) { if ( currentValue.getType().isPrimitive() || currentValue.getType().isEnum() ) {
inlineBuilder.append( "&& " ).append( currentValue.getName() ).append( " != $1)" ); inlineBuilder.append( "if(" ).append( currentValue.getName() ).append( " != $1)" );
} }
//simple data types //simple data types
else if ( currentValue.getType().getName().startsWith( "java.lang" ) else if ( currentValue.getType().getName().startsWith( "java.lang" )
@ -1169,11 +1167,11 @@ public class Enhancer {
|| currentValue.getType().getName().startsWith( "java.sql.Date" ) || currentValue.getType().getName().startsWith( "java.sql.Date" )
|| currentValue.getType().getName().startsWith( "java.util.Date" ) || currentValue.getType().getName().startsWith( "java.util.Date" )
|| currentValue.getType().getName().startsWith( "java.util.Calendar" ) ) { || currentValue.getType().getName().startsWith( "java.util.Calendar" ) ) {
inlineBuilder.append( "&& ((" ) inlineBuilder.append( "if(" )
.append( currentValue.getName() ) .append( currentValue.getName() )
.append( " == null) || (!" ) .append( " == null || !" )
.append( currentValue.getName() ) .append( currentValue.getName() )
.append( ".equals( $1))))" ); .append( ".equals( $1))" );
} }
//all other objects //all other objects
else { else {
@ -1192,11 +1190,11 @@ public class Enhancer {
} }
//todo: for now just call equals, should probably do something else here //todo: for now just call equals, should probably do something else here
inlineBuilder.append( "&& ((" ) inlineBuilder.append( "if(" )
.append( currentValue.getName() ) .append( currentValue.getName() )
.append( " == null) || (!" ) .append( " == null || !" )
.append( currentValue.getName() ) .append( currentValue.getName() )
.append( ".equals( $1))))" ); .append( ".equals( $1))" );
} }
inlineBuilder.append( EnhancerConstants.TRACKER_CHANGER_NAME + "(\"" ) inlineBuilder.append( EnhancerConstants.TRACKER_CHANGER_NAME + "(\"" )

View File

@ -23,21 +23,10 @@
*/ */
package org.hibernate.test.bytecode.enhancement; package org.hibernate.test.bytecode.enhancement;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javassist.ClassPool; import javassist.ClassPool;
import javassist.CtClass; import javassist.CtClass;
import javassist.CtField; import javassist.CtField;
import javassist.LoaderClassPath; import javassist.LoaderClassPath;
import org.hibernate.EntityMode;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.bytecode.enhance.spi.EnhancementContext; import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.enhance.spi.Enhancer; import org.hibernate.bytecode.enhance.spi.Enhancer;
@ -46,14 +35,20 @@ import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.ManagedEntity; import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.PersistentAttributeInterceptor; import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.spi.Status; import org.hibernate.engine.spi.Status;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.ManyToMany; import javax.persistence.ManyToMany;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping; import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -186,14 +181,14 @@ public class EnhancerTest extends BaseUnitTestCase {
assertSame( entityInstance, nextGetter.invoke( entityInstance ) ); assertSame( entityInstance, nextGetter.invoke( entityInstance ) );
// add an attribute interceptor... // add an attribute interceptor...
Method interceptorGetter = entityClass.getMethod( EnhancerConstants.INTERCEPTOR_GETTER_NAME ); // Method interceptorGetter = entityClass.getMethod( EnhancerConstants.INTERCEPTOR_GETTER_NAME );
Method interceptorSetter = entityClass.getMethod( EnhancerConstants.INTERCEPTOR_SETTER_NAME, PersistentAttributeInterceptor.class ); // Method interceptorSetter = entityClass.getMethod( EnhancerConstants.INTERCEPTOR_SETTER_NAME, PersistentAttributeInterceptor.class );
//
assertNull( interceptorGetter.invoke( entityInstance ) ); // assertNull( interceptorGetter.invoke( entityInstance ) );
entityClass.getMethod( "getId" ).invoke( entityInstance ); // entityClass.getMethod( "getId" ).invoke( entityInstance );
//
interceptorSetter.invoke( entityInstance, new LocalPersistentAttributeInterceptor() ); // interceptorSetter.invoke( entityInstance, new LocalPersistentAttributeInterceptor() );
assertNotNull(interceptorGetter.invoke(entityInstance)); // assertNotNull(interceptorGetter.invoke(entityInstance));
// dirty checking is unfortunately just printlns for now... just verify the test output // dirty checking is unfortunately just printlns for now... just verify the test output
entityClass.getMethod( "getId" ).invoke( entityInstance ); entityClass.getMethod( "getId" ).invoke( entityInstance );