HHH-11820 - Simplify dirty tracking on entities without collections [javassist]

This commit is contained in:
barreiro 2017-07-25 02:44:41 +01:00 committed by Gail Badner
parent e99eb2b7a2
commit c392d20dec
2 changed files with 143 additions and 47 deletions

View File

@ -21,6 +21,7 @@ import javassist.Modifier;
import javassist.NotFoundException;
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.SimpleFieldTracker;
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
@ -120,16 +121,84 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
loadCtClassFromClass( DirtyTracker.class ),
EnhancerConstants.TRACKER_FIELD_NAME
);
FieldWriter.addField(
managedCtClass,
loadCtClassFromClass( CollectionTracker.class ),
EnhancerConstants.TRACKER_COLLECTION_NAME
);
createDirtyTrackerMethods( managedCtClass );
if ( collectCollectionFields( managedCtClass ).isEmpty() ) {
createDirtyTrackerMethodsWithoutCollections( managedCtClass );
}
else {
FieldWriter.addField(
managedCtClass,
loadCtClassFromClass( CollectionTracker.class ),
EnhancerConstants.TRACKER_COLLECTION_NAME
);
createDirtyTrackerMethodsWithCollections( managedCtClass );
}
}
private void createDirtyTrackerMethods(CtClass managedCtClass) {
private void createDirtyTrackerMethodsWithoutCollections(CtClass managedCtClass) {
try {
MethodWriter.write(
managedCtClass,
"public void %1$s(String name) {%n" +
" if (%2$s == null) { %2$s = new %3$s(); }%n" +
" %2$s.add(name);%n" +
"}",
EnhancerConstants.TRACKER_CHANGER_NAME,
EnhancerConstants.TRACKER_FIELD_NAME,
DIRTY_TRACKER_IMPL
);
MethodWriter.write(
managedCtClass,
"public String[] %1$s() {%n" +
" return (%2$s == null) ? new String[0] : %2$s.get();%n" +
"}",
EnhancerConstants.TRACKER_GET_NAME,
EnhancerConstants.TRACKER_FIELD_NAME
);
MethodWriter.write(
managedCtClass,
"public boolean %1$s() {%n" +
" return (%2$s != null && !%2$s.isEmpty());%n" +
"}",
EnhancerConstants.TRACKER_HAS_CHANGED_NAME,
EnhancerConstants.TRACKER_FIELD_NAME
);
MethodWriter.write(
managedCtClass,
"public void %1$s() {%n" +
" if (%2$s != null) { %2$s.clear(); }%n" +
"}",
EnhancerConstants.TRACKER_CLEAR_NAME,
EnhancerConstants.TRACKER_FIELD_NAME
);
MethodWriter.write(
managedCtClass,
"public void %1$s(boolean f) {%n" +
" if (%2$s == null) %2$s = new %3$s();%n %2$s.suspend(f);%n" +
"}",
EnhancerConstants.TRACKER_SUSPEND_NAME,
EnhancerConstants.TRACKER_FIELD_NAME ,
DIRTY_TRACKER_IMPL
);
MethodWriter.write(
managedCtClass,
"public %s %s() { return %s.INSTANCE; }",
CollectionTracker.class.getName(),
EnhancerConstants.TRACKER_COLLECTION_GET_NAME,
NoopCollectionTracker.class.getName()
);
}
catch (CannotCompileException cce) {
cce.printStackTrace();
}
}
private void createDirtyTrackerMethodsWithCollections(CtClass managedCtClass) {
try {
MethodWriter.write(
managedCtClass,
@ -216,7 +285,7 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
continue;
}
if ( enhancementContext.isPersistentField( ctField ) ) {
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
collectionList.add( ctField );
@ -246,10 +315,12 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
List<CtField> collectionList = new ArrayList<CtField>();
for ( CtField ctField : managedCtSuperclass.getDeclaredFields() ) {
if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
collectionList.add( ctField );
if ( !Modifier.isStatic( ctField.getModifiers() ) ) {
if ( enhancementContext.isPersistentField( ctField ) && !enhancementContext.isMappedCollection( ctField ) ) {
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
collectionList.add( ctField );
}
}
}
}
@ -275,17 +346,15 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
);
for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
if ( !enhancementContext.isMappedCollection( ctField ) ) {
body.append(
String.format(
" // collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { return true; }%n" +
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { return true; }%n%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
body.append(
String.format(
" // collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { return true; }%n" +
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { return true; }%n%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
body.append( " return false;%n}" );
@ -311,17 +380,15 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
);
for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
if ( !enhancementContext.isMappedCollection( ctField ) ) {
body.append(
String.format(
" // Collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { tracker.add(\"%1$s\"); }%n" +
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { tracker.add(\"%1$s\"); }%n%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
body.append(
String.format(
" // Collection field [%1$s]%n" +
" if (%1$s == null && %2$s.getSize(\"%1$s\") != -1) { tracker.add(\"%1$s\"); }%n" +
" if (%1$s != null && %2$s.getSize(\"%1$s\") != %1$s.size()) { tracker.add(\"%1$s\"); }%n%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
body.append( "}" );
@ -359,19 +426,17 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
}
for ( CtField ctField : collectCollectionFields( managedCtClass ) ) {
if ( !enhancementContext.isMappedCollection( ctField ) ) {
body.append(
String.format(
" // collection field [%1$s]%n" +
" if (lazyInterceptor == null || lazyInterceptor.isAttributeLoaded(\"%1$s\")) {%n" +
" if (%1$s == null) { %2$s.add(\"%1$s\", -1); }%n" +
" else { %2$s.add(\"%1$s\", %1$s.size()); }%n" +
" }%n%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
body.append(
String.format(
" // collection field [%1$s]%n" +
" if (lazyInterceptor == null || lazyInterceptor.isAttributeLoaded(\"%1$s\")) {%n" +
" if (%1$s == null) { %2$s.add(\"%1$s\", -1); }%n" +
" else { %2$s.add(\"%1$s\", %1$s.size()); }%n" +
" }%n%n",
ctField.getName(),
EnhancerConstants.TRACKER_COLLECTION_NAME
)
);
}
body.append( "}" );

View File

@ -0,0 +1,31 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.enhance.internal.tracker;
import org.hibernate.bytecode.enhance.spi.CollectionTracker;
import java.util.Arrays;
/**
* small low memory class to keep track of the number of elements in a collection
*
* @author <a href="mailto:stale.pedersen@jboss.org">Ståle W. Pedersen</a>
*/
public final class NoopCollectionTracker implements CollectionTracker {
public static final CollectionTracker INSTANCE = new NoopCollectionTracker();
@Override
public void add(String name, int size) {
}
@Override
public int getSize(String name) {
return -1;
}
}