HHH-16940 add typesafe ref to ManagedType in metamodel classes

This commit is contained in:
Gavin King 2023-07-16 14:34:46 +02:00
parent 8611abe902
commit 5cee742698
5 changed files with 148 additions and 39 deletions

View File

@ -655,6 +655,12 @@ public class MetadataContext {
final Class<?> metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() );
// we found the class; so populate it...
registerAttributes( metamodelClass, managedType );
try {
injectField( metamodelClass, "class_", managedType, false );
}
catch (NoSuchFieldException e) {
// ignore
}
}
catch (ClassNotFoundException ignore) {
// nothing to do...
@ -715,13 +721,27 @@ public class MetadataContext {
attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED
|| attribute.getDeclaringType().getPersistenceType() == Type.PersistenceType.EMBEDDABLE;
injectField( metamodelClass, name, attribute, allowNonDeclaredFieldReference );
}
catch (NoSuchFieldException e) {
LOG.unableToLocateStaticMetamodelField( metamodelClass.getName(), name );
// throw new AssertionFailure(
// "Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name
// );
}
}
private static <X> void injectField(
Class<?> metamodelClass, String name, Object model,
boolean allowNonDeclaredFieldReference)
throws NoSuchFieldException {
final Field field = allowNonDeclaredFieldReference
? metamodelClass.getField( name )
: metamodelClass.getDeclaredField( name );
? metamodelClass.getField(name)
: metamodelClass.getDeclaredField(name);
try {
// should be public anyway, but to be sure...
ReflectHelper.ensureAccessibility( field );
field.set( null, attribute );
field.set( null, model);
}
catch (IllegalAccessException e) {
// todo : exception type?
@ -745,18 +765,11 @@ public class MetadataContext {
LOG.illegalArgumentOnStaticMetamodelFieldInjection(
metamodelClass.getName(),
name,
attribute.getClass().getName(),
model.getClass().getName(),
field.getType().getName()
);
}
}
catch (NoSuchFieldException e) {
LOG.unableToLocateStaticMetamodelField( metamodelClass.getName(), name );
// throw new AssertionFailure(
// "Unable to locate static metamodel field : " + metamodelClass.getName() + '#' + name
// );
}
}
public MappedSuperclassDomainType<?> locateMappedSuperclassType(MappedSuperclass mappedSuperclass) {
return mappedSuperclassByMappedSuperclassMapping.get( mappedSuperclass );

View File

@ -187,7 +187,7 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
final TypeElement typeElement = context.getElementUtils().getTypeElement( elementName );
try {
final AnnotationMetaEntity metaEntity =
AnnotationMetaEntity.create( typeElement, context, false );
AnnotationMetaEntity.create( typeElement, context, false, false );
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
context.removeElementToRedo( elementName );
}
@ -212,7 +212,7 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
if ( containsAnnotation( member, HQL, SQL, FIND ) ) {
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
final AnnotationMetaEntity metaEntity =
AnnotationMetaEntity.create( typeElement, context, false );
AnnotationMetaEntity.create( typeElement, context, false, false );
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
break;
}
@ -357,7 +357,7 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
= containsAnnotation( element, Constants.EMBEDDABLE )
|| containsAnnotation( element, Constants.MAPPED_SUPERCLASS );
final AnnotationMetaEntity metaEntity =
AnnotationMetaEntity.create( typeElement, context, requiresLazyMemberInitialization );
AnnotationMetaEntity.create( typeElement, context, requiresLazyMemberInitialization, true );
if ( alreadyExistingMetaEntity != null ) {
metaEntity.mergeInMembers( alreadyExistingMetaEntity );
}
@ -370,7 +370,7 @@ public class JPAMetaModelEntityProcessor extends AbstractProcessor {
private void handleRootElementAuxiliaryAnnotationMirrors(final Element element) {
if ( element instanceof TypeElement ) {
final AnnotationMetaEntity metaEntity =
AnnotationMetaEntity.create( (TypeElement) element, context, false );
AnnotationMetaEntity.create( (TypeElement) element, context, false, false );
context.addMetaAuxiliary( metaEntity.getQualifiedName(), metaEntity );
}
else if ( element instanceof PackageElement ) {

View File

@ -85,6 +85,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
private final TypeElement element;
private final Map<String, MetaAttribute> members;
private final Context context;
private final boolean managed;
private AccessTypeInformation entityAccessTypeInfo;
@ -120,15 +121,16 @@ public class AnnotationMetaEntity extends AnnotationMeta {
private final Map<String,String> memberTypes = new HashMap<>();
public AnnotationMetaEntity(TypeElement element, Context context) {
public AnnotationMetaEntity(TypeElement element, Context context, boolean managed) {
this.element = element;
this.context = context;
this.managed = managed;
this.members = new HashMap<>();
this.importContext = new ImportContextImpl( getPackageName( context, element ) );
}
public static AnnotationMetaEntity create(TypeElement element, Context context, boolean lazilyInitialised) {
final AnnotationMetaEntity annotationMetaEntity = new AnnotationMetaEntity( element, context );
public static AnnotationMetaEntity create(TypeElement element, Context context, boolean lazilyInitialised, boolean managed) {
final AnnotationMetaEntity annotationMetaEntity = new AnnotationMetaEntity( element, context, managed );
if ( !lazilyInitialised ) {
annotationMetaEntity.init();
}
@ -283,6 +285,10 @@ public class AnnotationMetaEntity extends AnnotationMeta {
findSessionGetter( methodsOfClass );
if ( managed ) {
putMember( "class", new AnnotationMetaType(this) );
}
addPersistentMembers( fieldsOfClass, AccessType.FIELD );
addPersistentMembers( gettersAndSettersOfClass, AccessType.PROPERTY );

View File

@ -0,0 +1,86 @@
/*
* 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.jpamodelgen.annotation;
import org.hibernate.jpamodelgen.model.MetaAttribute;
import org.hibernate.jpamodelgen.model.Metamodel;
import org.hibernate.jpamodelgen.util.Constants;
import org.hibernate.metamodel.model.domain.ManagedDomainType;
import static org.hibernate.jpamodelgen.util.TypeUtils.hasAnnotation;
/**
* @author Gavin King
*/
public class AnnotationMetaType implements MetaAttribute {
private final AnnotationMetaEntity annotationMetaEntity;
public AnnotationMetaType(AnnotationMetaEntity annotationMetaEntity) {
this.annotationMetaEntity = annotationMetaEntity;
}
@Override
public boolean hasTypedAttribute() {
return true;
}
@Override
public boolean hasStringAttribute() {
return false;
}
@Override
public String getAttributeDeclarationString() {
return new StringBuilder()
.append("\n/**\n * @see ")
.append( annotationMetaEntity.getQualifiedName() )
.append( "\n **/\n" )
.append("public static volatile ")
.append(annotationMetaEntity.importType(getTypeDeclaration()))
.append("<")
.append(annotationMetaEntity.importType(annotationMetaEntity.getQualifiedName()))
.append(">")
.append(" class_;").toString();
}
@Override
public String getAttributeNameDeclarationString() {
throw new UnsupportedOperationException();
}
@Override
public String getMetaType() {
return ManagedDomainType.class.getName();
}
@Override
public String getPropertyName() {
return "class";
}
@Override
public String getTypeDeclaration() {
if ( hasAnnotation(annotationMetaEntity.getElement(), Constants.ENTITY) ) {
return "jakarta.persistence.metamodel.EntityType";
}
else if ( hasAnnotation(annotationMetaEntity.getElement(), Constants.EMBEDDABLE) ) {
return "jakarta.persistence.metamodel.EmbeddableType";
}
else if ( hasAnnotation(annotationMetaEntity.getElement(), Constants.MAPPED_SUPERCLASS) ) {
return "jakarta.persistence.metamodel.MappedSuperclassType";
}
else {
return "jakarta.persistence.metamodel.ManagedType";
}
}
@Override
public Metamodel getHostingEntity() {
return annotationMetaEntity;
}
}

View File

@ -211,6 +211,10 @@ public final class TypeUtils {
return null;
}
public static boolean hasAnnotation(Element element, String qualifiedName) {
return getAnnotationMirror( element, qualifiedName ) != null;
}
public static @Nullable Object getAnnotationValue(AnnotationMirror annotationMirror, String parameterValue) {
assert annotationMirror != null;
assert parameterValue != null;