HHH-10981 - Support private persistent fields in @MappedSuperclass
This commit is contained in:
parent
6030f1ff94
commit
d23deb37cd
|
@ -27,12 +27,18 @@ import org.hibernate.internal.util.compare.EqualsHelper;
|
|||
*/
|
||||
public abstract class AttributeTypeDescriptor {
|
||||
|
||||
protected InheritanceMetadata inheritanceMetadata;
|
||||
|
||||
protected AttributeTypeDescriptor(InheritanceMetadata inheritanceMetadata) {
|
||||
this.inheritanceMetadata = inheritanceMetadata;
|
||||
}
|
||||
|
||||
public abstract String buildReadInterceptionBodyFragment(String fieldName);
|
||||
|
||||
public abstract String buildWriteInterceptionBodyFragment(String fieldName);
|
||||
|
||||
public String buildInLineDirtyCheckingBodyFragment(EnhancementContext context, CtField currentValue) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
try {
|
||||
// should ignore primary keys
|
||||
if ( PersistentAttributesHelper.hasAnnotation( currentValue, Id.class )
|
||||
|
@ -40,9 +46,13 @@ public abstract class AttributeTypeDescriptor {
|
|||
return "";
|
||||
}
|
||||
|
||||
String readFragment = inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible()
|
||||
? "super." + inheritanceMetadata.getReaderName() + "()"
|
||||
: "this." + currentValue.getName();
|
||||
|
||||
if ( currentValue.getType().isPrimitive() || currentValue.getType().isEnum() ) {
|
||||
// primitives || enums
|
||||
builder.append( String.format( " if (%s != $1)", currentValue.getName() ) );
|
||||
builder.append( String.format( " if ( %s != $1 )", readFragment ) );
|
||||
}
|
||||
else {
|
||||
// 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(
|
||||
" if ( !%s.areEqual( %s, $1 ) )",
|
||||
EqualsHelper.class.getName(),
|
||||
currentValue.getName()
|
||||
readFragment
|
||||
)
|
||||
);
|
||||
}
|
||||
builder.append( String.format( " { %s(\"%s\"); }", EnhancerConstants.TRACKER_CHANGER_NAME, currentValue.getName() ) );
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
catch (NotFoundException ignore) {
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
@ -75,33 +84,39 @@ public abstract class AttributeTypeDescriptor {
|
|||
/**
|
||||
* factory method to get the AttributeTypeDescriptor for a particular field type
|
||||
*/
|
||||
public static AttributeTypeDescriptor resolve(CtField persistentField) throws NotFoundException {
|
||||
if ( persistentField.getType() == CtClass.booleanType ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Boolean.TYPE );
|
||||
public static AttributeTypeDescriptor resolve(CtClass managedCtClass, CtField persistentField) throws NotFoundException {
|
||||
boolean inherited = !managedCtClass.equals( persistentField.getDeclaringClass() );
|
||||
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 ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Byte.TYPE );
|
||||
else if ( CtClass.byteType.equals( persistentField.getType() )) {
|
||||
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Byte.TYPE );
|
||||
}
|
||||
else if ( persistentField.getType() == CtClass.charType ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Character.TYPE );
|
||||
else if ( CtClass.charType.equals( persistentField.getType() ) ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Character.TYPE );
|
||||
}
|
||||
else if ( persistentField.getType() == CtClass.shortType ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Short.TYPE );
|
||||
else if ( CtClass.shortType.equals( persistentField.getType() ) ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Short.TYPE );
|
||||
}
|
||||
else if ( persistentField.getType() == CtClass.intType ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Integer.TYPE );
|
||||
else if ( CtClass.intType.equals( persistentField.getType() ) ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Integer.TYPE );
|
||||
}
|
||||
else if ( persistentField.getType() == CtClass.longType ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Long.TYPE );
|
||||
else if ( CtClass.longType.equals( persistentField.getType() ) ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Long.TYPE );
|
||||
}
|
||||
else if ( persistentField.getType() == CtClass.doubleType ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Double.TYPE );
|
||||
else if ( CtClass.doubleType.equals( persistentField.getType() ) ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Double.TYPE );
|
||||
}
|
||||
else if ( persistentField.getType() == CtClass.floatType ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( Float.TYPE );
|
||||
else if ( CtClass.floatType.equals( persistentField.getType() ) ) {
|
||||
return new PrimitiveAttributeTypeDescriptor( inheritanceMetadata, Float.TYPE );
|
||||
}
|
||||
else {
|
||||
return new ObjectAttributeTypeDescriptor( persistentField.getType() );
|
||||
return new ObjectAttributeTypeDescriptor( inheritanceMetadata, persistentField.getType() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,19 +129,45 @@ public abstract class AttributeTypeDescriptor {
|
|||
|
||||
private final String type;
|
||||
|
||||
private ObjectAttributeTypeDescriptor(CtClass concreteType) {
|
||||
private ObjectAttributeTypeDescriptor(InheritanceMetadata inheritanceMetadata, CtClass concreteType) {
|
||||
super( inheritanceMetadata );
|
||||
this.type = concreteType.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildReadInterceptionBodyFragment(String fieldName) {
|
||||
if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
|
||||
return String.format(
|
||||
" if( %3$s() != null ) { super.%5$s( (%2$s) %3$s().readObject(this, \"%1$s\", super.%4$s())); }%n",
|
||||
fieldName,
|
||||
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) {
|
||||
if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
|
||||
return String.format(
|
||||
" %2$s localVar = $1;%n" +
|
||||
" if ( %3$s() != null ) { localVar = (%2$s) %3$s().writeObject(this, \"%1$s\", super.%4$s(), $1); }%n" +
|
||||
" super.%5$s(localVar);",
|
||||
fieldName,
|
||||
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" +
|
||||
|
@ -136,6 +177,7 @@ public abstract class AttributeTypeDescriptor {
|
|||
EnhancerConstants.INTERCEPTOR_GETTER_NAME );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AttributeTypeDescriptor for primitive types
|
||||
|
@ -144,7 +186,8 @@ public abstract class AttributeTypeDescriptor {
|
|||
|
||||
private final String type;
|
||||
|
||||
private PrimitiveAttributeTypeDescriptor(Class<?> primitiveType) {
|
||||
private PrimitiveAttributeTypeDescriptor(InheritanceMetadata inheritanceMetadata, Class<?> primitiveType) {
|
||||
super( inheritanceMetadata );
|
||||
if ( !primitiveType.isPrimitive() ) {
|
||||
throw new IllegalArgumentException( "Primitive attribute type descriptor can only be used on primitive types" );
|
||||
}
|
||||
|
@ -152,15 +195,41 @@ public abstract class AttributeTypeDescriptor {
|
|||
this.type = primitiveType.getSimpleName().substring( 0, 1 ).toUpperCase( Locale.ROOT ) + primitiveType.getSimpleName().substring( 1 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildReadInterceptionBodyFragment(String fieldName) {
|
||||
if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
|
||||
return String.format(
|
||||
" if (%3$s() != null ) { super.%5$s( %3$s().read%2$s(this, \"%1$s\", super.%4$s())); }",
|
||||
fieldName,
|
||||
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) {
|
||||
if ( inheritanceMetadata.isInherited() && !inheritanceMetadata.isVisible() ) {
|
||||
return String.format(
|
||||
" %2$s localVar = $1;%n" +
|
||||
" if ( %4$s() != null ) { localVar = %4$s().write%3$s(this, \"%1$s\", super.%5$s(), $1); }%n" +
|
||||
" super.%6$s(localVar);",
|
||||
fieldName,
|
||||
type.toLowerCase( Locale.ROOT ),
|
||||
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" +
|
||||
|
@ -172,5 +241,39 @@ public abstract class AttributeTypeDescriptor {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.bytecode.enhance.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -17,6 +19,7 @@ import javassist.CtClass;
|
|||
import javassist.CtField;
|
||||
import javassist.Modifier;
|
||||
|
||||
import javassist.NotFoundException;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.DirtyTracker;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.SimpleCollectionTracker;
|
||||
import org.hibernate.bytecode.enhance.internal.tracker.SimpleFieldTracker;
|
||||
|
@ -206,7 +209,7 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
|
|||
}
|
||||
|
||||
private List<CtField> collectCollectionFields(CtClass managedCtClass) {
|
||||
final List<CtField> collectionList = new LinkedList<CtField>();
|
||||
List<CtField> collectionList = new ArrayList<>();
|
||||
|
||||
for ( CtField ctField : managedCtClass.getDeclaredFields() ) {
|
||||
// skip static fields and skip fields added by enhancement
|
||||
|
@ -222,20 +225,41 @@ public class EntityEnhancer extends PersistentAttributesEnhancer {
|
|||
}
|
||||
|
||||
// HHH-10646 Add fields inherited from @MappedSuperclass
|
||||
for ( CtField ctField : managedCtClass.getDeclaredFields() ) {
|
||||
if ( !enhancementContext.isMappedSuperclassClass( ctField.getDeclaringClass() ) || Modifier.isStatic( ctField.getModifiers() ) ) {
|
||||
continue;
|
||||
// HHH-10981 There is no need to do it for @MappedSuperclass
|
||||
if ( !enhancementContext.isMappedSuperclassClass( managedCtClass ) ) {
|
||||
collectionList.addAll( collectInheritCollectionFields( managedCtClass ) );
|
||||
}
|
||||
if ( enhancementContext.isPersistentField( ctField ) ) {
|
||||
|
||||
return collectionList;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collectionList.addAll( collectInheritCollectionFields( managedCtSuperclass ) );
|
||||
return collectionList;
|
||||
}
|
||||
catch ( NotFoundException nfe ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private void createCollectionDirtyCheckMethod(CtClass managedCtClass) {
|
||||
try {
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
*/
|
||||
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.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -76,42 +80,60 @@ public class PersistentAttributesEnhancer extends Enhancer {
|
|||
}
|
||||
|
||||
private CtField[] collectPersistentFields(CtClass managedCtClass) {
|
||||
final List<CtField> persistentFieldList = new LinkedList<CtField>();
|
||||
List<CtField> persistentFieldList = new ArrayList<CtField>();
|
||||
for ( CtField ctField : managedCtClass.getDeclaredFields() ) {
|
||||
// skip static fields and skip fields added by enhancement
|
||||
if ( Modifier.isStatic( ctField.getModifiers() ) || ctField.getName().startsWith( "$$_hibernate_" ) ) {
|
||||
// skip static fields and skip fields added by enhancement and outer reference in inner classes
|
||||
if ( ctField.getName().startsWith( "$$_hibernate_" ) || "this$0".equals( ctField.getName() ) ) {
|
||||
continue;
|
||||
}
|
||||
// skip outer reference in inner classes
|
||||
if ( "this$0".equals( ctField.getName() ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( enhancementContext.isPersistentField( ctField ) ) {
|
||||
if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
|
||||
persistentFieldList.add( ctField );
|
||||
}
|
||||
}
|
||||
// HHH-10646 Add fields inherited from @MappedSuperclass
|
||||
// CtClass.getFields() does not return private fields, while CtClass.getDeclaredFields() does not return inherit
|
||||
for ( CtField ctField : managedCtClass.getFields() ) {
|
||||
if ( ctField.getDeclaringClass().equals( managedCtClass ) ) {
|
||||
// Already processed above
|
||||
// HHH-10981 There is no need to do it for @MappedSuperclass
|
||||
if ( !enhancementContext.isMappedSuperclassClass( managedCtClass ) ) {
|
||||
persistentFieldList.addAll( collectInheritPersistentFields( managedCtClass ) );
|
||||
}
|
||||
|
||||
CtField[] orderedFields = enhancementContext.order( persistentFieldList.toArray( new CtField[0] ) );
|
||||
log.debugf( "Persistent fields for entity %s: %s", managedCtClass.getName(), Arrays.toString( orderedFields ));
|
||||
return orderedFields;
|
||||
}
|
||||
|
||||
private Collection<CtField> collectInheritPersistentFields(CtClass managedCtClass) {
|
||||
if ( managedCtClass == null || Object.class.getName().equals( managedCtClass.getName() ) ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
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 ( !enhancementContext.isMappedSuperclassClass( ctField.getDeclaringClass() ) || Modifier.isStatic( ctField.getModifiers() ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( enhancementContext.isPersistentField( ctField ) ) {
|
||||
if ( !Modifier.isStatic( ctField.getModifiers() ) && enhancementContext.isPersistentField( ctField ) ) {
|
||||
persistentFieldList.add( ctField );
|
||||
}
|
||||
}
|
||||
return enhancementContext.order( persistentFieldList.toArray( new CtField[persistentFieldList.size()] ) );
|
||||
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) {
|
||||
private PersistentAttributeAccessMethods enhancePersistentAttribute( CtClass managedCtClass, CtField persistentField) {
|
||||
try {
|
||||
final AttributeTypeDescriptor typeDescriptor = AttributeTypeDescriptor.resolve( persistentField );
|
||||
AttributeTypeDescriptor typeDescriptor = AttributeTypeDescriptor.resolve( managedCtClass, persistentField );
|
||||
return new PersistentAttributeAccessMethods(
|
||||
generateFieldReader( managedCtClass, persistentField, typeDescriptor ),
|
||||
generateFieldWriter( managedCtClass, persistentField, typeDescriptor )
|
||||
|
@ -131,25 +153,58 @@ public class PersistentAttributesEnhancer extends Enhancer {
|
|||
CtClass managedCtClass,
|
||||
CtField persistentField,
|
||||
AttributeTypeDescriptor typeDescriptor) {
|
||||
final String fieldName = persistentField.getName();
|
||||
final String readerName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName;
|
||||
String fieldName = persistentField.getName();
|
||||
String readerName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName;
|
||||
String writerName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + fieldName;
|
||||
CtMethod tmpSuperReader = null;
|
||||
CtMethod tmpSuperWriter = null;
|
||||
CtMethod reader = null;
|
||||
|
||||
try {
|
||||
boolean declared = persistentField.getDeclaringClass().equals( managedCtClass );
|
||||
String declaredReadFragment = "this." + fieldName + "";
|
||||
String superReadFragment = "super." + readerName + "()";
|
||||
|
||||
if (!declared) {
|
||||
// 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 ) ) {
|
||||
return MethodWriter.addGetter( managedCtClass, fieldName, readerName );
|
||||
reader = MethodWriter.write(
|
||||
managedCtClass, "public %s %s() { return %s;%n}",
|
||||
persistentField.getType().getName(),
|
||||
readerName,
|
||||
declared ? declaredReadFragment : superReadFragment
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
return MethodWriter.write(
|
||||
managedCtClass, "public %s %s() {%n%s%n return this.%s;%n}",
|
||||
else {
|
||||
reader = MethodWriter.write(
|
||||
managedCtClass, "public %s %s() {%n%s%n return %s;%n}",
|
||||
persistentField.getType().getName(),
|
||||
readerName,
|
||||
typeDescriptor.buildReadInterceptionBodyFragment( fieldName ),
|
||||
fieldName
|
||||
declared ? declaredReadFragment : superReadFragment
|
||||
);
|
||||
}
|
||||
if ( tmpSuperReader != null ) {
|
||||
persistentField.getDeclaringClass().removeMethod( tmpSuperReader );
|
||||
}
|
||||
if ( tmpSuperWriter != null ) {
|
||||
persistentField.getDeclaringClass().removeMethod( tmpSuperWriter );
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
catch (CannotCompileException cce) {
|
||||
final String msg = String.format(
|
||||
"Could not enhance entity class [%s] to add field reader method [%s]",
|
||||
|
@ -172,15 +227,39 @@ public class PersistentAttributesEnhancer extends Enhancer {
|
|||
CtClass managedCtClass,
|
||||
CtField persistentField,
|
||||
AttributeTypeDescriptor typeDescriptor) {
|
||||
final String fieldName = persistentField.getName();
|
||||
final String writerName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + fieldName;
|
||||
String fieldName = persistentField.getName();
|
||||
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 {
|
||||
final CtMethod writer;
|
||||
boolean declared = persistentField.getDeclaringClass().equals( managedCtClass );
|
||||
String declaredWriteFragment = "this." + fieldName + "=" + fieldName + ";";
|
||||
String superWriteFragment = "super." + writerName + "(" + fieldName + ");";
|
||||
|
||||
if ( !enhancementContext.hasLazyLoadableAttributes( managedCtClass )
|
||||
|| !enhancementContext.isLazyLoadable( persistentField ) ) {
|
||||
writer = MethodWriter.addSetter( managedCtClass, fieldName, writerName );
|
||||
if (!declared) {
|
||||
// create a temporary setter 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 );
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
writer = MethodWriter.write(
|
||||
|
@ -203,12 +282,7 @@ public class PersistentAttributesEnhancer extends Enhancer {
|
|||
);
|
||||
}
|
||||
else {
|
||||
writer.insertBefore(
|
||||
typeDescriptor.buildInLineDirtyCheckingBodyFragment(
|
||||
enhancementContext,
|
||||
persistentField
|
||||
)
|
||||
);
|
||||
writer.insertBefore( typeDescriptor.buildInLineDirtyCheckingBodyFragment( enhancementContext, persistentField ) );
|
||||
}
|
||||
|
||||
handleCompositeField( managedCtClass, persistentField, writer );
|
||||
|
@ -217,6 +291,13 @@ public class PersistentAttributesEnhancer extends Enhancer {
|
|||
if ( enhancementContext.doBiDirectionalAssociationManagement( persistentField ) ) {
|
||||
handleBiDirectionalAssociation( managedCtClass, persistentField, writer );
|
||||
}
|
||||
|
||||
if ( tmpSuperReader != null ) {
|
||||
persistentField.getDeclaringClass().removeMethod( tmpSuperReader );
|
||||
}
|
||||
if ( tmpSuperWriter != null ) {
|
||||
persistentField.getDeclaringClass().removeMethod( tmpSuperWriter );
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
catch (CannotCompileException cce) {
|
||||
|
|
|
@ -172,6 +172,13 @@ public class EnhancerTest extends BaseUnitTestCase {
|
|||
@TestForIssue( jiraKey = "HHH-10646" )
|
||||
public void testMappedSuperclass() {
|
||||
EnhancerTestUtils.runEnhancerTestTask( MappedSuperclassTestTask.class );
|
||||
EnhancerTestUtils.runEnhancerTestTask( MappedSuperclassTestTask.class, new EnhancerTestContext() {
|
||||
@Override
|
||||
public boolean hasLazyLoadableAttributes(CtClass classDescriptor) {
|
||||
// HHH-10981 - Without lazy loading, the generation of getters and setters has a different code path
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -29,7 +29,7 @@ public class MappedSuperclassTestTask extends AbstractEnhancerTestTask {
|
|||
|
||||
public void execute() {
|
||||
Employee charles = new Employee( "Charles", "Engineer" );
|
||||
charles.oca = 1002;
|
||||
charles.setOca( 1002 );
|
||||
|
||||
// Check that both types of class attributes are being dirty tracked
|
||||
EnhancerTestUtils.checkDirtyTracking( charles, "title", "oca" );
|
||||
|
@ -47,9 +47,9 @@ public class MappedSuperclassTestTask extends AbstractEnhancerTestTask {
|
|||
|
||||
@MappedSuperclass private static class Person {
|
||||
|
||||
@Id String name;
|
||||
@Id private String name;
|
||||
|
||||
@Version long oca;
|
||||
@Version private long oca;
|
||||
|
||||
public Person(String name) {
|
||||
this();
|
||||
|
|
Loading…
Reference in New Issue