HHH-10981 - Support private persistent fields in @MappedSuperclass
This commit is contained in:
parent
63af953566
commit
e2641afb12
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue