HHH-11820 - Simplify dirty tracking on entities without collections [bytebuddy]
This commit is contained in:
parent
c392d20dec
commit
d0e7fab351
|
@ -14,6 +14,7 @@ import java.util.Map;
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker;
|
import org.hibernate.bytecode.enhance.internal.tracker.CompositeOwnerTracker;
|
||||||
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
|
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
|
||||||
|
import org.hibernate.bytecode.enhance.internal.tracker.NoopCollectionTracker;
|
||||||
import org.hibernate.bytecode.enhance.internal.tracker.SimpleCollectionTracker;
|
import org.hibernate.bytecode.enhance.internal.tracker.SimpleCollectionTracker;
|
||||||
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
|
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
|
||||||
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
|
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
|
||||||
|
@ -83,7 +84,23 @@ class CodeTemplates {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AreCollectionFieldsDirty {
|
static class GetDirtyAttributesWithoutCollections {
|
||||||
|
@Advice.OnMethodExit
|
||||||
|
static void $$_hibernate_getDirtyAttributes(
|
||||||
|
@Advice.Return(readOnly = false) String[] returned,
|
||||||
|
@Advice.FieldValue(value = EnhancerConstants.TRACKER_FIELD_NAME) DirtyTracker $$_hibernate_tracker) {
|
||||||
|
returned = $$_hibernate_tracker == null ? new String[0] : $$_hibernate_tracker.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class GetCollectionTrackerWithoutCollections {
|
||||||
|
@Advice.OnMethodExit
|
||||||
|
static void $$_hibernate_getCollectionTracker( @Advice.Return(readOnly = false) CollectionTracker returned) {
|
||||||
|
returned = NoopCollectionTracker.INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AreFieldsDirty {
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
static void $$_hibernate_hasDirtyAttributes(
|
static void $$_hibernate_hasDirtyAttributes(
|
||||||
@Advice.This ExtendedSelfDirtinessTracker self,
|
@Advice.This ExtendedSelfDirtinessTracker self,
|
||||||
|
@ -93,6 +110,15 @@ class CodeTemplates {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class AreFieldsDirtyWithoutCollections {
|
||||||
|
@Advice.OnMethodExit
|
||||||
|
static void $$_hibernate_hasDirtyAttributes(
|
||||||
|
@Advice.Return(readOnly = false) boolean returned,
|
||||||
|
@Advice.FieldValue(value = EnhancerConstants.TRACKER_FIELD_NAME) DirtyTracker $$_hibernate_tracker) {
|
||||||
|
returned = $$_hibernate_tracker != null && !$$_hibernate_tracker.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class ClearDirtyAttributes {
|
static class ClearDirtyAttributes {
|
||||||
@Advice.OnMethodEnter
|
@Advice.OnMethodEnter
|
||||||
static void $$_hibernate_clearDirtyAttributes(
|
static void $$_hibernate_clearDirtyAttributes(
|
||||||
|
@ -105,6 +131,16 @@ class CodeTemplates {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class ClearDirtyAttributesWithoutCollections {
|
||||||
|
@Advice.OnMethodEnter
|
||||||
|
static void $$_hibernate_clearDirtyAttributes(
|
||||||
|
@Advice.FieldValue(value = EnhancerConstants.TRACKER_FIELD_NAME) DirtyTracker $$_hibernate_tracker) {
|
||||||
|
if ( $$_hibernate_tracker != null ) {
|
||||||
|
$$_hibernate_tracker.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class SuspendDirtyTracking {
|
static class SuspendDirtyTracking {
|
||||||
@Advice.OnMethodEnter
|
@Advice.OnMethodEnter
|
||||||
static void $$_hibernate_suspendDirtyTracking(
|
static void $$_hibernate_suspendDirtyTracking(
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.engine.spi.ManagedEntity;
|
||||||
import org.hibernate.engine.spi.ManagedMappedSuperclass;
|
import org.hibernate.engine.spi.ManagedMappedSuperclass;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
||||||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ import net.bytebuddy.implementation.Implementation;
|
||||||
import net.bytebuddy.implementation.StubMethod;
|
import net.bytebuddy.implementation.StubMethod;
|
||||||
import net.bytebuddy.pool.TypePool;
|
import net.bytebuddy.pool.TypePool;
|
||||||
|
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.isDefaultFinalizer;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isGetter;
|
import static net.bytebuddy.matcher.ElementMatchers.isGetter;
|
||||||
|
|
||||||
public class EnhancerImpl implements Enhancer {
|
public class EnhancerImpl implements Enhancer {
|
||||||
|
@ -95,7 +97,7 @@ public class EnhancerImpl implements Enhancer {
|
||||||
try {
|
try {
|
||||||
final TypeDescription managedCtClass = classPool.describe( className ).resolve();
|
final TypeDescription managedCtClass = classPool.describe( className ).resolve();
|
||||||
DynamicType.Builder<?> builder = doEnhance(
|
DynamicType.Builder<?> builder = doEnhance(
|
||||||
new ByteBuddy().with( TypeValidation.DISABLED ).redefine( managedCtClass, ClassFileLocator.Simple.of( className, originalBytes ) ),
|
new ByteBuddy().ignore( isDefaultFinalizer() ).with( TypeValidation.DISABLED ).redefine( managedCtClass, ClassFileLocator.Simple.of( className, originalBytes ) ),
|
||||||
managedCtClass
|
managedCtClass
|
||||||
);
|
);
|
||||||
if ( builder == null ) {
|
if ( builder == null ) {
|
||||||
|
@ -161,6 +163,26 @@ public class EnhancerImpl implements Enhancer {
|
||||||
builder = addInterceptorHandling( builder, managedCtClass );
|
builder = addInterceptorHandling( builder, managedCtClass );
|
||||||
|
|
||||||
if ( enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
|
if ( enhancementContext.doDirtyCheckingInline( managedCtClass ) ) {
|
||||||
|
if ( collectCollectionFields( managedCtClass ).isEmpty() ) {
|
||||||
|
builder = builder.implement( SelfDirtinessTracker.class )
|
||||||
|
.defineField( EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
||||||
|
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
||||||
|
.defineMethod( EnhancerConstants.TRACKER_CHANGER_NAME, void.class, Visibility.PUBLIC )
|
||||||
|
.withParameters( String.class )
|
||||||
|
.intercept( Advice.to( CodeTemplates.TrackChange.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
|
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
|
||||||
|
.intercept( Advice.to( CodeTemplates.GetDirtyAttributesWithoutCollections.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
|
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
||||||
|
.intercept( Advice.to( CodeTemplates.AreFieldsDirtyWithoutCollections.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
|
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
||||||
|
.intercept( Advice.to( CodeTemplates.ClearDirtyAttributesWithoutCollections.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
|
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
|
||||||
|
.withParameters( boolean.class )
|
||||||
|
.intercept( Advice.to( CodeTemplates.SuspendDirtyTracking.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
|
.defineMethod( EnhancerConstants.TRACKER_COLLECTION_GET_NAME, CollectionTracker.class, Visibility.PUBLIC )
|
||||||
|
.intercept( Advice.to( CodeTemplates.GetCollectionTrackerWithoutCollections.class ).wrap( StubMethod.INSTANCE ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
builder = builder.implement( ExtendedSelfDirtinessTracker.class )
|
builder = builder.implement( ExtendedSelfDirtinessTracker.class )
|
||||||
.defineField( EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
.defineField( EnhancerConstants.TRACKER_FIELD_NAME, DirtyTracker.class, FieldManifestation.TRANSIENT, Visibility.PRIVATE )
|
||||||
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
.annotateField( AnnotationDescription.Builder.ofType( Transient.class ).build() )
|
||||||
|
@ -172,7 +194,7 @@ public class EnhancerImpl implements Enhancer {
|
||||||
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
|
.defineMethod( EnhancerConstants.TRACKER_GET_NAME, String[].class, Visibility.PUBLIC )
|
||||||
.intercept( Advice.to( CodeTemplates.GetDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
.intercept( Advice.to( CodeTemplates.GetDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
.defineMethod( EnhancerConstants.TRACKER_HAS_CHANGED_NAME, boolean.class, Visibility.PUBLIC )
|
||||||
.intercept( Advice.to( CodeTemplates.AreCollectionFieldsDirty.class ).wrap( StubMethod.INSTANCE ) )
|
.intercept( Advice.to( CodeTemplates.AreFieldsDirty.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
.defineMethod( EnhancerConstants.TRACKER_CLEAR_NAME, void.class, Visibility.PUBLIC )
|
||||||
.intercept( Advice.to( CodeTemplates.ClearDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
.intercept( Advice.to( CodeTemplates.ClearDirtyAttributes.class ).wrap( StubMethod.INSTANCE ) )
|
||||||
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
|
.defineMethod( EnhancerConstants.TRACKER_SUSPEND_NAME, void.class, Visibility.PUBLIC )
|
||||||
|
@ -183,7 +205,6 @@ public class EnhancerImpl implements Enhancer {
|
||||||
|
|
||||||
Implementation isDirty = StubMethod.INSTANCE, getDirtyNames = StubMethod.INSTANCE, clearDirtyNames = StubMethod.INSTANCE;
|
Implementation isDirty = StubMethod.INSTANCE, getDirtyNames = StubMethod.INSTANCE, clearDirtyNames = StubMethod.INSTANCE;
|
||||||
for ( FieldDescription collectionField : collectCollectionFields( managedCtClass ) ) {
|
for ( FieldDescription collectionField : collectCollectionFields( managedCtClass ) ) {
|
||||||
if ( !enhancementContext.isMappedCollection( collectionField ) ) {
|
|
||||||
if ( collectionField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
if ( collectionField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||||
isDirty = Advice.withCustomMapping()
|
isDirty = Advice.withCustomMapping()
|
||||||
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
|
.bind( CodeTemplates.FieldName.class, collectionField.getName() )
|
||||||
|
@ -219,7 +240,6 @@ public class EnhancerImpl implements Enhancer {
|
||||||
.wrap( clearDirtyNames );
|
.wrap( clearDirtyNames );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) {
|
if ( enhancementContext.hasLazyLoadableAttributes( managedCtClass ) ) {
|
||||||
clearDirtyNames = Advice.to( CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class ).wrap( clearDirtyNames );
|
clearDirtyNames = Advice.to( CodeTemplates.InitializeLazyAttributeLoadingInterceptor.class ).wrap( clearDirtyNames );
|
||||||
|
@ -236,6 +256,7 @@ public class EnhancerImpl implements Enhancer {
|
||||||
.withParameters( LazyAttributeLoadingInterceptor.class )
|
.withParameters( LazyAttributeLoadingInterceptor.class )
|
||||||
.intercept( clearDirtyNames );
|
.intercept( clearDirtyNames );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return transformer.applyTo( builder, false );
|
return transformer.applyTo( builder, false );
|
||||||
}
|
}
|
||||||
|
@ -340,7 +361,7 @@ public class EnhancerImpl implements Enhancer {
|
||||||
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
|
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( enhancementContext.isPersistentField( ctField ) ) {
|
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
|
||||||
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||||
collectionList.add( ctField );
|
collectionList.add( ctField );
|
||||||
}
|
}
|
||||||
|
@ -368,12 +389,14 @@ public class EnhancerImpl implements Enhancer {
|
||||||
List<FieldDescription> collectionList = new ArrayList<FieldDescription>();
|
List<FieldDescription> collectionList = new ArrayList<FieldDescription>();
|
||||||
|
|
||||||
for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) {
|
for ( FieldDescription ctField : managedCtSuperclass.getDeclaredFields() ) {
|
||||||
if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
|
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
|
||||||
|
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
|
||||||
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
if ( ctField.getType().asErasure().isAssignableTo( Collection.class ) || ctField.getType().asErasure().isAssignableTo( Map.class ) ) {
|
||||||
collectionList.add( ctField );
|
collectionList.add( ctField );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
collectionList.addAll( collectInheritCollectionFields( managedCtSuperclass ) );
|
collectionList.addAll( collectInheritCollectionFields( managedCtSuperclass ) );
|
||||||
return collectionList;
|
return collectionList;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue