HHH-10981 - Support private persistent fields in @MappedSuperclass

This commit is contained in:
barreiro 2016-07-22 03:10:04 +01:00 committed by Andrea Boriero
parent 63af953566
commit e2641afb12
3 changed files with 316 additions and 115 deletions

View File

@ -27,12 +27,18 @@ import org.hibernate.internal.util.compare.EqualsHelper;
*/ */
public abstract class AttributeTypeDescriptor { public abstract class AttributeTypeDescriptor {
protected InheritanceMetadata inheritanceMetadata;
protected AttributeTypeDescriptor(InheritanceMetadata inheritanceMetadata) {
this.inheritanceMetadata = inheritanceMetadata;
}
public abstract String buildReadInterceptionBodyFragment(String fieldName); public abstract String buildReadInterceptionBodyFragment(String fieldName);
public abstract String buildWriteInterceptionBodyFragment(String fieldName); public abstract String buildWriteInterceptionBodyFragment(String fieldName);
public String buildInLineDirtyCheckingBodyFragment(EnhancementContext context, CtField currentValue) { public String buildInLineDirtyCheckingBodyFragment(EnhancementContext context, CtField currentValue) {
final StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
try { try {
// should ignore primary keys // should ignore primary keys
if ( PersistentAttributesHelper.hasAnnotation( currentValue, Id.class ) if ( PersistentAttributesHelper.hasAnnotation( currentValue, Id.class )
@ -40,9 +46,13 @@ public abstract class AttributeTypeDescriptor {
return ""; return "";
} }
String readFragment = inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible()
? "super." + inheritanceMetadata.getReaderName() + "()"
: "this." + currentValue.getName();
if ( currentValue.getType().isPrimitive() || currentValue.getType().isEnum() ) { if ( currentValue.getType().isPrimitive() || currentValue.getType().isEnum() ) {
// primitives || enums // primitives || enums
builder.append( String.format( " if (%s != $1)", currentValue.getName() ) ); builder.append( String.format( " if ( %s != $1 )", readFragment ) );
} }
else { else {
// if the field is a collection we return since we handle that in a separate method // if the field is a collection we return since we handle that in a separate method
@ -58,14 +68,13 @@ public abstract class AttributeTypeDescriptor {
String.format( String.format(
" if ( !%s.areEqual( %s, $1 ) )", " if ( !%s.areEqual( %s, $1 ) )",
EqualsHelper.class.getName(), EqualsHelper.class.getName(),
currentValue.getName() readFragment
) )
); );
} }
builder.append( String.format( " { %s(\"%s\"); }", EnhancerConstants.TRACKER_CHANGER_NAME, currentValue.getName() ) ); builder.append( String.format( " { %s(\"%s\"); }", EnhancerConstants.TRACKER_CHANGER_NAME, currentValue.getName() ) );
} }
catch (NotFoundException e) { catch (NotFoundException ignore) {
e.printStackTrace();
} }
return builder.toString(); return builder.toString();
} }
@ -75,33 +84,39 @@ public abstract class AttributeTypeDescriptor {
/** /**
* factory method to get the AttributeTypeDescriptor for a particular field type * factory method to get the AttributeTypeDescriptor for a particular field type
*/ */
public static AttributeTypeDescriptor resolve(CtField persistentField) throws NotFoundException { public static AttributeTypeDescriptor resolve(CtClass managedCtClass, CtField persistentField) throws NotFoundException {
if ( persistentField.getType() == CtClass.booleanType ) { boolean inherited = !managedCtClass.equals( persistentField.getDeclaringClass() );
return new PrimitiveAttributeTypeDescriptor( Boolean.TYPE ); boolean visible = persistentField.visibleFrom( managedCtClass );
String readerName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + persistentField.getName();
String writerName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + persistentField.getName();
InheritanceMetadata inheritanceMetadata = new InheritanceMetadata( inherited, visible, readerName, writerName );
if ( CtClass.booleanType.equals( persistentField.getType() ) ) {
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Boolean.TYPE );
} }
else if ( persistentField.getType() == CtClass.byteType ) { else if ( CtClass.byteType.equals( persistentField.getType() )) {
return new PrimitiveAttributeTypeDescriptor( Byte.TYPE ); return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Byte.TYPE );
} }
else if ( persistentField.getType() == CtClass.charType ) { else if ( CtClass.charType.equals( persistentField.getType() ) ) {
return new PrimitiveAttributeTypeDescriptor( Character.TYPE ); return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Character.TYPE );
} }
else if ( persistentField.getType() == CtClass.shortType ) { else if ( CtClass.shortType.equals( persistentField.getType() ) ) {
return new PrimitiveAttributeTypeDescriptor( Short.TYPE ); return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Short.TYPE );
} }
else if ( persistentField.getType() == CtClass.intType ) { else if ( CtClass.intType.equals( persistentField.getType() ) ) {
return new PrimitiveAttributeTypeDescriptor( Integer.TYPE ); return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Integer.TYPE );
} }
else if ( persistentField.getType() == CtClass.longType ) { else if ( CtClass.longType.equals( persistentField.getType() ) ) {
return new PrimitiveAttributeTypeDescriptor( Long.TYPE ); return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Long.TYPE );
} }
else if ( persistentField.getType() == CtClass.doubleType ) { else if ( CtClass.doubleType.equals( persistentField.getType() ) ) {
return new PrimitiveAttributeTypeDescriptor( Double.TYPE ); return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Double.TYPE );
} }
else if ( persistentField.getType() == CtClass.floatType ) { else if ( CtClass.floatType.equals( persistentField.getType() ) ) {
return new PrimitiveAttributeTypeDescriptor( Float.TYPE ); return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Float.TYPE );
} }
else { else {
return new ObjectAttributeTypeDescriptor( persistentField.getType() ); return new ObjectAttributeTypeDescriptor( inheritanceMetadata, persistentField.getType() );
} }
} }
@ -114,26 +129,53 @@ public abstract class AttributeTypeDescriptor {
private final String type; private final String type;
private ObjectAttributeTypeDescriptor(CtClass concreteType) { private ObjectAttributeTypeDescriptor(InheritanceMetadata inheritanceMetadata, CtClass concreteType) {
super( inheritanceMetadata );
this.type = concreteType.getName(); this.type = concreteType.getName();
} }
@Override
public String buildReadInterceptionBodyFragment(String fieldName) { public String buildReadInterceptionBodyFragment(String fieldName) {
return String.format( if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
" if ( %3$s() != null ) { this.%1$s = (%2$s) %3$s().readObject(this, \"%1$s\", this.%1$s); }%n", return String.format(
fieldName, " if( %3$s() != null ) { super.%5$s( (%2$s) %3$s().readObject(this, \"%1$s\", super.%4$s())); }%n",
type, fieldName,
EnhancerConstants.INTERCEPTOR_GETTER_NAME ); type,
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
inheritanceMetadata.getReaderName(),
inheritanceMetadata.getWriterName() );
}
else {
return String.format(
" if ( %3$s() != null ) { this.%1$s = (%2$s) %3$s().readObject(this, \"%1$s\", this.%1$s); }%n",
fieldName,
type,
EnhancerConstants.INTERCEPTOR_GETTER_NAME );
}
} }
@Override
public String buildWriteInterceptionBodyFragment(String fieldName) { public String buildWriteInterceptionBodyFragment(String fieldName) {
return String.format( if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
" %2$s localVar = $1;%n" + return String.format(
" if ( %3$s() != null ) { localVar = (%2$s) %3$s().writeObject(this, \"%1$s\", this.%1$s, $1); }%n" + " %2$s localVar = $1;%n" +
" this.%1$s = localVar;", " if ( %3$s() != null ) { localVar = (%2$s) %3$s().writeObject(this, \"%1$s\", super.%4$s(), $1); }%n" +
fieldName, " super.%5$s(localVar);",
type, fieldName,
EnhancerConstants.INTERCEPTOR_GETTER_NAME ); type,
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
inheritanceMetadata.getReaderName(),
inheritanceMetadata.getWriterName() );
}
else {
return String.format(
" %2$s localVar = $1;%n" +
" if ( %3$s() != null ) { localVar = (%2$s) %3$s().writeObject(this, \"%1$s\", this.%1$s, $1); }%n" +
" this.%1$s = localVar;",
fieldName,
type,
EnhancerConstants.INTERCEPTOR_GETTER_NAME );
}
} }
} }
@ -144,7 +186,8 @@ public abstract class AttributeTypeDescriptor {
private final String type; private final String type;
private PrimitiveAttributeTypeDescriptor(Class<?> primitiveType) { private PrimitiveAttributeTypeDescriptor(InheritanceMetadata inheritanceMetadata, Class<?> primitiveType) {
super( inheritanceMetadata );
if ( !primitiveType.isPrimitive() ) { if ( !primitiveType.isPrimitive() ) {
throw new IllegalArgumentException( "Primitive attribute type descriptor can only be used on primitive types" ); throw new IllegalArgumentException( "Primitive attribute type descriptor can only be used on primitive types" );
} }
@ -152,24 +195,84 @@ public abstract class AttributeTypeDescriptor {
this.type = primitiveType.getSimpleName().substring( 0, 1 ).toUpperCase( Locale.ROOT ) + primitiveType.getSimpleName().substring( 1 ); this.type = primitiveType.getSimpleName().substring( 0, 1 ).toUpperCase( Locale.ROOT ) + primitiveType.getSimpleName().substring( 1 );
} }
@Override
public String buildReadInterceptionBodyFragment(String fieldName) { public String buildReadInterceptionBodyFragment(String fieldName) {
return String.format( if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
" if (%3$s() != null ) { this.%1$s = %3$s().read%2$s(this, \"%1$s\", this.%1$s); }", return String.format(
fieldName, " if (%3$s() != null ) { super.%5$s( %3$s().read%2$s(this, \"%1$s\", super.%4$s())); }",
type, fieldName,
EnhancerConstants.INTERCEPTOR_GETTER_NAME ); type,
EnhancerConstants.INTERCEPTOR_GETTER_NAME,
inheritanceMetadata.getReaderName(),
inheritanceMetadata.getWriterName() );
}
else {
return String.format(
" if (%3$s() != null ) { this.%1$s = %3$s().read%2$s(this, \"%1$s\", this.%1$s); }",
fieldName,
type,
EnhancerConstants.INTERCEPTOR_GETTER_NAME );
}
} }
@Override
public String buildWriteInterceptionBodyFragment(String fieldName) { public String buildWriteInterceptionBodyFragment(String fieldName) {
return String.format( if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
" %2$s localVar = $1;%n" + return String.format(
" if ( %4$s() != null ) { localVar = %4$s().write%3$s(this, \"%1$s\", this.%1$s, $1); }%n" + " %2$s localVar = $1;%n" +
" this.%1$s = localVar;", " if ( %4$s() != null ) { localVar = %4$s().write%3$s(this, \"%1$s\", super.%5$s(), $1); }%n" +
fieldName, " super.%6$s(localVar);",
type.toLowerCase( Locale.ROOT ), fieldName,
type, type.toLowerCase( Locale.ROOT ),
EnhancerConstants.INTERCEPTOR_GETTER_NAME type,
); EnhancerConstants.INTERCEPTOR_GETTER_NAME,
inheritanceMetadata.getReaderName(),
inheritanceMetadata.getWriterName() );
}
else {
return String.format(
" %2$s localVar = $1;%n" +
" if ( %4$s() != null ) { localVar = %4$s().write%3$s(this, \"%1$s\", this.%1$s, $1); }%n" +
" this.%1$s = localVar;",
fieldName,
type.toLowerCase( Locale.ROOT ),
type,
EnhancerConstants.INTERCEPTOR_GETTER_NAME
);
}
}
}
//
private static class InheritanceMetadata {
private boolean inherited;
private boolean visible;
private String readerName;
private String writerName;
public InheritanceMetadata(boolean inherited, boolean visible, String readerName, String writerName) {
this.inherited = inherited;
this.visible = visible;
this.readerName = readerName;
this.writerName = writerName;
}
public boolean isInherited() {
return inherited;
}
public boolean isVisible() {
return visible;
}
public String getReaderName() {
return readerName;
}
public String getWriterName() {
return writerName;
} }
} }

View File

@ -6,7 +6,9 @@
*/ */
package org.hibernate.bytecode.enhance.internal; package org.hibernate.bytecode.enhance.internal;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -17,6 +19,7 @@ import javassist.CtClass;
import javassist.CtField; import javassist.CtField;
import javassist.Modifier; import javassist.Modifier;
import javassist.NotFoundException;
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker; import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
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;
@ -206,7 +209,7 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
} }
private List<CtField> collectCollectionFields(CtClass managedCtClass) { private List<CtField> collectCollectionFields(CtClass managedCtClass) {
final List<CtField> collectionList = new LinkedList<CtField>(); List<CtField> collectionList = new ArrayList<>();
for ( CtField ctField : managedCtClass.getDeclaredFields() ) { for ( CtField ctField : managedCtClass.getDeclaredFields() ) {
// skip static fields and skip fields added by enhancement // skip static fields and skip fields added by enhancement
@ -222,19 +225,36 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
} }
// HHH-10646 Add fields inherited from @MappedSuperclass // HHH-10646 Add fields inherited from @MappedSuperclass
for ( CtField ctField : managedCtClass.getDeclaredFields() ) { collectionList.addAll( collectInheritCollectionFields( managedCtClass ) );
if ( !enhancementContext.isMappedSuperclassClass( ctField.getDeclaringClass() ) || Modifier.isStatic( ctField.getModifiers() ) ) { return collectionList;
continue; }
private Collection<CtField> collectInheritCollectionFields(CtClass managedCtClass) {
if ( managedCtClass == null || Object.class.getName().equals( managedCtClass.getName() ) ) {
return Collections.emptyList();
}
try {
CtClass managedCtSuperclass = managedCtClass.getSuperclass();
if ( !enhancementContext.isMappedSuperclassClass( managedCtSuperclass ) ) {
return collectInheritCollectionFields( managedCtSuperclass );
} }
if ( enhancementContext.isPersistentField( ctField ) ) { List<CtField> collectionList = new ArrayList<CtField>();
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) { for ( CtField ctField : managedCtSuperclass.getDeclaredFields() ) {
collectionList.add( ctField ); if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
if ( PersistentAttributesHelper.isAssignable( ctField, Collection.class.getName() ) ||
PersistentAttributesHelper.isAssignable( ctField, Map.class.getName() ) ) {
collectionList.add( ctField );
}
} }
} }
collectionList.addAll( collectInheritCollectionFields( managedCtSuperclass ) );
return collectionList;
}
catch ( NotFoundException nfe ) {
return Collections.emptyList();
} }
return collectionList;
} }
private void createCollectionDirtyCheckMethod(CtClass managedCtClass) { private void createCollectionDirtyCheckMethod(CtClass managedCtClass) {

View File

@ -6,6 +6,10 @@
*/ */
package org.hibernate.bytecode.enhance.internal; package org.hibernate.bytecode.enhance.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -76,42 +80,57 @@ public class PersistentAttributesEnhancer extends Enhancer {
} }
private CtField[] collectPersistentFields(CtClass managedCtClass) { private CtField[] collectPersistentFields(CtClass managedCtClass) {
final List<CtField> persistentFieldList = new LinkedList<CtField>(); List<CtField> persistentFieldList = new ArrayList<CtField>();
for ( CtField ctField : managedCtClass.getDeclaredFields() ) { for ( CtField ctField : managedCtClass.getDeclaredFields() ) {
// skip static fields and skip fields added by enhancement // skip static fields and skip fields added by enhancement and outer reference in inner classes
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) { if ( ctField.getName().startsWith( "$$_hibernate_" ) || "this$0".equals( ctField.getName() ) ) {
continue; continue;
} }
// skip outer reference in inner classes if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
if ( "this$0".equals( ctField.getName() ) ) {
continue;
}
if ( enhancementContext.isPersistentField( ctField ) ) {
persistentFieldList.add( ctField ); persistentFieldList.add( ctField );
} }
} }
// HHH-10646 Add fields inherited from @MappedSuperclass // HHH-10646 Add fields inherited from @MappedSuperclass
// CtClass.getFields() does not return private fields, while CtClass.getDeclaredFields() does not return inherit persistentFieldList.addAll( collectInheritPersistentFields( managedCtClass ) );
for ( CtField ctField : managedCtClass.getFields() ) {
if ( ctField.getDeclaringClass().equals( managedCtClass ) ) { CtField[] orderedFields = enhancementContext.order( persistentFieldList.toArray( new CtField[0] ) );
// Already processed above log.debugf( "Persistent fields for entity %s: %s", managedCtClass.getName(), Arrays.toString( orderedFields ));
continue; return orderedFields;
}
if ( !enhancementContext.isMappedSuperclassClass( ctField.getDeclaringClass() ) || Modifier.isStatic( ctField.getModifiers() ) ) {
continue;
}
if ( enhancementContext.isPersistentField( ctField ) ) {
persistentFieldList.add( ctField );
}
}
return enhancementContext.order( persistentFieldList.toArray( new CtField[persistentFieldList.size()] ) );
} }
private PersistentAttributeAccessMethods enhancePersistentAttribute( private Collection<CtField> collectInheritPersistentFields(CtClass managedCtClass) {
CtClass managedCtClass, if ( managedCtClass == null || Object.class.getName().equals( managedCtClass.getName() ) ) {
CtField persistentField) { return Collections.emptyList();
}
try { try {
final AttributeTypeDescriptor typeDescriptor = AttributeTypeDescriptor.resolve( persistentField ); CtClass managedCtSuperclass = managedCtClass.getSuperclass();
if ( !enhancementContext.isMappedSuperclassClass( managedCtSuperclass ) ) {
return collectInheritPersistentFields( managedCtSuperclass );
}
log.debugf( "Found @MappedSuperclass %s to collectPersistenceFields", managedCtSuperclass.getName() );
List<CtField> persistentFieldList = new ArrayList<CtField>();
for ( CtField ctField : managedCtSuperclass.getDeclaredFields() ) {
if ( ctField.getName().startsWith( "$$_hibernate_" ) || "this$0".equals( ctField.getName() ) ) {
continue;
}
if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
persistentFieldList.add( ctField );
}
}
persistentFieldList.addAll( collectInheritPersistentFields( managedCtSuperclass ) );
return persistentFieldList;
}
catch ( NotFoundException nfe ) {
log.warnf( "Could not find the superclass of %s", managedCtClass );
return Collections.emptyList();
}
}
private PersistentAttributeAccessMethods enhancePersistentAttribute( CtClass managedCtClass, CtField persistentField) {
try {
AttributeTypeDescriptor typeDescriptor = AttributeTypeDescriptor.resolve( managedCtClass, persistentField );
return new PersistentAttributeAccessMethods( return new PersistentAttributeAccessMethods(
generateFieldReader( managedCtClass, persistentField, typeDescriptor ), generateFieldReader( managedCtClass, persistentField, typeDescriptor ),
generateFieldWriter( managedCtClass, persistentField, typeDescriptor ) generateFieldWriter( managedCtClass, persistentField, typeDescriptor )
@ -131,24 +150,57 @@ public class PersistentAttributesEnhancer extends Enhancer {
CtClass managedCtClass, CtClass managedCtClass,
CtField persistentField, CtField persistentField,
AttributeTypeDescriptor typeDescriptor) { AttributeTypeDescriptor typeDescriptor) {
final String fieldName = persistentField.getName(); String fieldName = persistentField.getName();
final String readerName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName; String readerName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName;
String writerName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + fieldName;
// read attempts only have to deal lazy-loading support, not dirty checking; CtMethod tmpSuperReader = null;
// so if the field is not enabled as lazy-loadable return a plain simple getter as the reader CtMethod tmpSuperWriter = null;
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) CtMethod reader = null;
|| !enhancementContext.isLazyLoadable( persistentField ) ) {
return MethodWriter.addGetter( managedCtClass, fieldName, readerName );
}
try { try {
return MethodWriter.write( boolean declared = persistentField.getDeclaringClass().equals( managedCtClass );
managedCtClass, "public %s %s() {%n%s%n return this.%s;%n}", String declaredReadFragment = "this." + fieldName + "";
persistentField.getType().getName(), String superReadFragment = "super." + readerName + "()";
readerName,
typeDescriptor.buildReadInterceptionBodyFragment( fieldName ), if (!declared) {
fieldName // create a temporary getter on the supper entity to be able to compile our code
); try {
persistentField.getDeclaringClass().getDeclaredMethod( readerName );
persistentField.getDeclaringClass().getDeclaredMethod( writerName );
}
catch (NotFoundException nfe){
tmpSuperReader = MethodWriter.addGetter( persistentField.getDeclaringClass(), persistentField.getName(), readerName );
tmpSuperWriter = MethodWriter.addSetter( persistentField.getDeclaringClass(), persistentField.getName(), writerName );
}
}
// read attempts only have to deal lazy-loading support, not dirty checking;
// so if the field is not enabled as lazy-loadable return a plain simple getter as the reader
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass )
|| !enhancementContext.isLazyLoadable( persistentField ) ) {
reader = MethodWriter.write(
managedCtClass, "public %s %s() { return %s;%n}",
persistentField.getType().getName(),
readerName,
declared ? declaredReadFragment : superReadFragment
);
}
else {
reader = MethodWriter.write(
managedCtClass, "public %s %s() {%n%s%n return %s;%n}",
persistentField.getType().getName(),
readerName,
typeDescriptor.buildReadInterceptionBodyFragment( fieldName ),
declared ? declaredReadFragment : superReadFragment
);
}
if ( tmpSuperReader != null ) {
persistentField.getDeclaringClass().removeMethod( tmpSuperReader );
}
if ( tmpSuperWriter != null ) {
persistentField.getDeclaringClass().removeMethod( tmpSuperWriter );
}
return reader;
} }
catch (CannotCompileException cce) { catch (CannotCompileException cce) {
final String msg = String.format( final String msg = String.format(
@ -172,15 +224,39 @@ public class PersistentAttributesEnhancer extends Enhancer {
CtClass managedCtClass, CtClass managedCtClass,
CtField persistentField, CtField persistentField,
AttributeTypeDescriptor typeDescriptor) { AttributeTypeDescriptor typeDescriptor) {
final String fieldName = persistentField.getName(); String fieldName = persistentField.getName();
final String writerName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + fieldName; String readerName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName;
String writerName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + fieldName;
CtMethod tmpSuperReader = null;
CtMethod tmpSuperWriter = null;
CtMethod writer;
try { try {
final CtMethod writer; boolean declared = persistentField.getDeclaringClass().equals( managedCtClass );
String declaredWriteFragment = "this." + fieldName + "=" + fieldName + ";";
String superWriteFragment = "super." + writerName + "(" + fieldName + ");";
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) if (!declared) {
|| !enhancementContext.isLazyLoadable( persistentField ) ) { // create a temporary setter on the supper entity to be able to compile our code
writer = MethodWriter.addSetter( managedCtClass, fieldName, writerName ); try {
persistentField.getDeclaringClass().getDeclaredMethod( readerName );
persistentField.getDeclaringClass().getDeclaredMethod( writerName );
}
catch (NotFoundException nfe){
tmpSuperReader = MethodWriter.addGetter( persistentField.getDeclaringClass(), persistentField.getName(), readerName );
tmpSuperWriter = MethodWriter.addSetter( persistentField.getDeclaringClass(), persistentField.getName(), writerName );
}
}
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass ) || !enhancementContext.isLazyLoadable( persistentField ) ) {
writer = MethodWriter.write(
managedCtClass,
"public void %s(%s %s) {%n %s%n}",
writerName,
persistentField.getType().getName(),
fieldName,
declared ? declaredWriteFragment : superWriteFragment
);
} }
else { else {
writer = MethodWriter.write( writer = MethodWriter.write(
@ -203,12 +279,7 @@ public class PersistentAttributesEnhancer extends Enhancer {
); );
} }
else { else {
writer.insertBefore( writer.insertBefore( typeDescriptor.buildInLineDirtyCheckingBodyFragment( enhancementContext, persistentField ) );
typeDescriptor.buildInLineDirtyCheckingBodyFragment(
enhancementContext,
persistentField
)
);
} }
handleCompositeField( managedCtClass, persistentField, writer ); handleCompositeField( managedCtClass, persistentField, writer );
@ -217,6 +288,13 @@ public class PersistentAttributesEnhancer extends Enhancer {
if ( enhancementContext.doBiDirectionalAssociationManagement( persistentField ) ) { if ( enhancementContext.doBiDirectionalAssociationManagement( persistentField ) ) {
handleBiDirectionalAssociation( managedCtClass, persistentField, writer ); handleBiDirectionalAssociation( managedCtClass, persistentField, writer );
} }
if ( tmpSuperReader != null ) {
persistentField.getDeclaringClass().removeMethod( tmpSuperReader );
}
if ( tmpSuperWriter != null ) {
persistentField.getDeclaringClass().removeMethod( tmpSuperWriter );
}
return writer; return writer;
} }
catch (CannotCompileException cce) { catch (CannotCompileException cce) {