HHH-17864 generate static metamodel fields for embeddables
This commit is contained in:
parent
b7038b2294
commit
f3dd73dd2f
|
@ -483,6 +483,8 @@ public class HibernateProcessor extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
addMetamodelToContext( typeElement, metaEntity );
|
addMetamodelToContext( typeElement, metaEntity );
|
||||||
if ( context.generateJakartaDataStaticMetamodel()
|
if ( context.generateJakartaDataStaticMetamodel()
|
||||||
|
// no static metamodel for embeddable classes in Jakarta Data
|
||||||
|
&& hasAnnotation( element, ENTITY, MAPPED_SUPERCLASS )
|
||||||
// Don't generate a Jakarta Data metamodel
|
// Don't generate a Jakarta Data metamodel
|
||||||
// if this entity was partially mapped in XML
|
// if this entity was partially mapped in XML
|
||||||
&& alreadyExistingMetaEntity == null ) {
|
&& alreadyExistingMetaEntity == null ) {
|
||||||
|
|
|
@ -734,24 +734,71 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
|
|
||||||
private void addPersistentMembers(List<? extends Element> membersOfClass, AccessType membersKind) {
|
private void addPersistentMembers(List<? extends Element> membersOfClass, AccessType membersKind) {
|
||||||
for ( Element memberOfClass : membersOfClass ) {
|
for ( Element memberOfClass : membersOfClass ) {
|
||||||
if ( isPersistent( memberOfClass, membersKind ) ) {
|
if ( isPersistent(memberOfClass, membersKind) ) {
|
||||||
|
addPersistentMember(memberOfClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPersistentMember(Element memberOfClass) {
|
||||||
if ( jakartaDataStaticModel ) {
|
if ( jakartaDataStaticModel ) {
|
||||||
final DataAnnotationMetaAttribute dataMetaAttribute =
|
final DataAnnotationMetaAttribute dataMetaAttribute =
|
||||||
memberOfClass.asType()
|
memberOfClass.asType()
|
||||||
.accept( new DataMetaAttributeGenerationVisitor( this, context ), memberOfClass );
|
.accept( new DataMetaAttributeGenerationVisitor(this, context), memberOfClass );
|
||||||
if ( dataMetaAttribute != null ) {
|
if ( dataMetaAttribute != null ) {
|
||||||
members.put( '_' + dataMetaAttribute.getPropertyName(), dataMetaAttribute );
|
final String path = dataMetaAttribute.getPropertyName();
|
||||||
|
members.put('_' + path, dataMetaAttribute);
|
||||||
|
if ( isEmbedded(memberOfClass) ) {
|
||||||
|
final TypeMirror type = attributeType(memberOfClass);
|
||||||
|
final DeclaredType declaredType = (DeclaredType) type;
|
||||||
|
final TypeElement typeElement = (TypeElement) declaredType.asElement();
|
||||||
|
for ( Element field : fieldsIn( typeElement.getEnclosedElements() ) ) {
|
||||||
|
addEmbeddablePersistentMember(field, path, AccessType.FIELD);
|
||||||
|
}
|
||||||
|
for ( Element method : methodsIn( typeElement.getEnclosedElements() ) ) {
|
||||||
|
if ( isGetterOrSetter(method) ) {
|
||||||
|
addEmbeddablePersistentMember(method, path, AccessType.PROPERTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final AnnotationMetaAttribute jpaMetaAttribute =
|
final AnnotationMetaAttribute jpaMetaAttribute =
|
||||||
memberOfClass.asType()
|
memberOfClass.asType()
|
||||||
.accept( new MetaAttributeGenerationVisitor( this, context ), memberOfClass );
|
.accept( new MetaAttributeGenerationVisitor( this, context ), memberOfClass);
|
||||||
if ( jpaMetaAttribute != null ) {
|
if ( jpaMetaAttribute != null ) {
|
||||||
members.put( jpaMetaAttribute.getPropertyName(), jpaMetaAttribute );
|
members.put( jpaMetaAttribute.getPropertyName(), jpaMetaAttribute );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addEmbeddablePersistentMember(Element memberOfEmbeddable, String path, AccessType membersKind) {
|
||||||
|
if ( isPersistent(memberOfEmbeddable, membersKind) ) { //TODO respect AccessType of embeddable
|
||||||
|
final DataAnnotationMetaAttribute metaAttribute =
|
||||||
|
memberOfEmbeddable.asType()
|
||||||
|
.accept( new DataMetaAttributeGenerationVisitor(this, path, context),
|
||||||
|
memberOfEmbeddable );
|
||||||
|
if (metaAttribute != null) {
|
||||||
|
members.put('_' + metaAttribute.getPropertyName(),
|
||||||
|
metaAttribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isEmbedded(Element memberOfClass) {
|
||||||
|
if ( hasAnnotation(memberOfClass, EMBEDDED) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final TypeMirror type = attributeType(memberOfClass);
|
||||||
|
if ( type.getKind() == TypeKind.DECLARED ) {
|
||||||
|
final DeclaredType declaredType = (DeclaredType) type;
|
||||||
|
return hasAnnotation( declaredType.asElement(), EMBEDDABLE );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.processor.annotation;
|
package org.hibernate.processor.annotation;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.processor.model.MetaAttribute;
|
import org.hibernate.processor.model.MetaAttribute;
|
||||||
import org.hibernate.processor.model.Metamodel;
|
import org.hibernate.processor.model.Metamodel;
|
||||||
|
|
||||||
|
@ -21,14 +22,17 @@ import static org.hibernate.processor.util.TypeUtils.propertyName;
|
||||||
*/
|
*/
|
||||||
public class DataAnnotationMetaAttribute implements MetaAttribute {
|
public class DataAnnotationMetaAttribute implements MetaAttribute {
|
||||||
|
|
||||||
final Element element;
|
private final Element element;
|
||||||
final AnnotationMetaEntity parent;
|
private final AnnotationMetaEntity parent;
|
||||||
private final String type;
|
private final String type;
|
||||||
|
private final @Nullable String path;
|
||||||
|
|
||||||
public DataAnnotationMetaAttribute(AnnotationMetaEntity parent, Element element, String type) {
|
public DataAnnotationMetaAttribute(
|
||||||
|
AnnotationMetaEntity parent, Element element, String type, @Nullable String path) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,7 +52,8 @@ public class DataAnnotationMetaAttribute implements MetaAttribute {
|
||||||
@Override
|
@Override
|
||||||
public String getAttributeDeclarationString() {
|
public String getAttributeDeclarationString() {
|
||||||
final String className = parent.importType( parent.getQualifiedName() );
|
final String className = parent.importType( parent.getQualifiedName() );
|
||||||
final String memberName = element.getSimpleName().toString();
|
final String elementName = element.getSimpleName().toString();
|
||||||
|
final String memberName = path == null ? elementName : path + '.' + elementName;
|
||||||
final String impl = isTextual()
|
final String impl = isTextual()
|
||||||
? parent.importType("jakarta.data.metamodel.impl.TextAttributeRecord")
|
? parent.importType("jakarta.data.metamodel.impl.TextAttributeRecord")
|
||||||
: parent.importType("jakarta.data.metamodel.impl.SortableAttributeRecord");
|
: parent.importType("jakarta.data.metamodel.impl.SortableAttributeRecord");
|
||||||
|
@ -63,22 +68,24 @@ public class DataAnnotationMetaAttribute implements MetaAttribute {
|
||||||
.append( "<" )
|
.append( "<" )
|
||||||
.append( className )
|
.append( className )
|
||||||
.append( "> " )
|
.append( "> " )
|
||||||
.append( getPropertyName() )
|
.append( getPropertyName().replace('.','_') )
|
||||||
.append(" = new ")
|
.append(" = new ")
|
||||||
.append( impl )
|
.append( impl )
|
||||||
.append( "<>(\"" )
|
.append( "<>(\"" )
|
||||||
.append(memberName)
|
.append( getPropertyName() )
|
||||||
.append( "\");" )
|
.append( "\");" )
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAttributeNameDeclarationString(){
|
public String getAttributeNameDeclarationString(){
|
||||||
|
final String fieldName =
|
||||||
|
getUpperUnderscoreCaseFromLowerCamelCase(getPropertyName().replace('.', '_'));
|
||||||
return new StringBuilder()
|
return new StringBuilder()
|
||||||
.append("public static final ")
|
.append("public static final ")
|
||||||
.append(parent.importType(String.class.getName()))
|
.append(parent.importType(String.class.getName()))
|
||||||
.append(" ")
|
.append(" ")
|
||||||
.append(getUpperUnderscoreCaseFromLowerCamelCase(getPropertyName()))
|
.append(fieldName)
|
||||||
.append(" = ")
|
.append(" = ")
|
||||||
.append("\"")
|
.append("\"")
|
||||||
.append(getPropertyName())
|
.append(getPropertyName())
|
||||||
|
@ -89,7 +96,8 @@ public class DataAnnotationMetaAttribute implements MetaAttribute {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPropertyName() {
|
public String getPropertyName() {
|
||||||
return propertyName( parent, element );
|
final String propertyName = propertyName(parent, element);
|
||||||
|
return path == null ? propertyName : path + '.' + propertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -33,10 +33,18 @@ public class DataMetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Null
|
||||||
|
|
||||||
private final AnnotationMetaEntity entity;
|
private final AnnotationMetaEntity entity;
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
private final @Nullable String path;
|
||||||
|
|
||||||
DataMetaAttributeGenerationVisitor(AnnotationMetaEntity entity, Context context) {
|
DataMetaAttributeGenerationVisitor(AnnotationMetaEntity entity, Context context) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.path = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataMetaAttributeGenerationVisitor(AnnotationMetaEntity entity, String path, Context context) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.context = context;
|
||||||
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Types typeUtils() {
|
private Types typeUtils() {
|
||||||
|
@ -45,19 +53,19 @@ public class DataMetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Null
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable DataAnnotationMetaAttribute visitPrimitive(PrimitiveType primitiveType, Element element) {
|
public @Nullable DataAnnotationMetaAttribute visitPrimitive(PrimitiveType primitiveType, Element element) {
|
||||||
return new DataAnnotationMetaAttribute( entity, element, toTypeString( primitiveType ) );
|
return new DataAnnotationMetaAttribute( entity, element, toTypeString( primitiveType ), path );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable DataAnnotationMetaAttribute visitArray(ArrayType arrayType, Element element) {
|
public @Nullable DataAnnotationMetaAttribute visitArray(ArrayType arrayType, Element element) {
|
||||||
return new DataAnnotationMetaAttribute( entity, element, toArrayTypeString( arrayType, context ) );
|
return new DataAnnotationMetaAttribute( entity, element, toArrayTypeString( arrayType, context ), path );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable DataAnnotationMetaAttribute visitTypeVariable(TypeVariable typeVariable, Element element) {
|
public @Nullable DataAnnotationMetaAttribute visitTypeVariable(TypeVariable typeVariable, Element element) {
|
||||||
// METAGEN-29 - for a type variable we use the upper bound
|
// METAGEN-29 - for a type variable we use the upper bound
|
||||||
return new DataAnnotationMetaAttribute( entity, element,
|
return new DataAnnotationMetaAttribute( entity, element,
|
||||||
typeUtils().erasure( typeVariable.getUpperBound() ).toString() );
|
typeUtils().erasure( typeVariable.getUpperBound() ).toString(), path );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,7 +80,7 @@ public class DataMetaAttributeGenerationVisitor extends SimpleTypeVisitor8<@Null
|
||||||
}
|
}
|
||||||
else if ( isBasicAttribute( element, returnedElement, context ) ) {
|
else if ( isBasicAttribute( element, returnedElement, context ) ) {
|
||||||
final String type = targetEntity != null ? targetEntity : returnedElement.getQualifiedName().toString();
|
final String type = targetEntity != null ? targetEntity : returnedElement.getQualifiedName().toString();
|
||||||
return new DataAnnotationMetaAttribute( entity, element, type );
|
return new DataAnnotationMetaAttribute( entity, element, type, path );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -22,6 +22,7 @@ public final class Constants {
|
||||||
public static final String ENTITY = "jakarta.persistence.Entity";
|
public static final String ENTITY = "jakarta.persistence.Entity";
|
||||||
public static final String MAPPED_SUPERCLASS = "jakarta.persistence.MappedSuperclass";
|
public static final String MAPPED_SUPERCLASS = "jakarta.persistence.MappedSuperclass";
|
||||||
public static final String EMBEDDABLE = "jakarta.persistence.Embeddable";
|
public static final String EMBEDDABLE = "jakarta.persistence.Embeddable";
|
||||||
|
public static final String EMBEDDED = "jakarta.persistence.Embedded";
|
||||||
public static final String ID = "jakarta.persistence.Id";
|
public static final String ID = "jakarta.persistence.Id";
|
||||||
public static final String ID_CLASS = "jakarta.persistence.IdClass";
|
public static final String ID_CLASS = "jakarta.persistence.IdClass";
|
||||||
public static final String EMBEDDED_ID = "jakarta.persistence.EmbeddedId";
|
public static final String EMBEDDED_ID = "jakarta.persistence.EmbeddedId";
|
||||||
|
|
|
@ -43,6 +43,7 @@ import static org.hibernate.processor.util.Constants.ACCESS;
|
||||||
import static org.hibernate.processor.util.Constants.BASIC;
|
import static org.hibernate.processor.util.Constants.BASIC;
|
||||||
import static org.hibernate.processor.util.Constants.ELEMENT_COLLECTION;
|
import static org.hibernate.processor.util.Constants.ELEMENT_COLLECTION;
|
||||||
import static org.hibernate.processor.util.Constants.EMBEDDABLE;
|
import static org.hibernate.processor.util.Constants.EMBEDDABLE;
|
||||||
|
import static org.hibernate.processor.util.Constants.EMBEDDED;
|
||||||
import static org.hibernate.processor.util.Constants.EMBEDDED_ID;
|
import static org.hibernate.processor.util.Constants.EMBEDDED_ID;
|
||||||
import static org.hibernate.processor.util.Constants.ENTITY;
|
import static org.hibernate.processor.util.Constants.ENTITY;
|
||||||
import static org.hibernate.processor.util.Constants.ID;
|
import static org.hibernate.processor.util.Constants.ID;
|
||||||
|
@ -551,7 +552,7 @@ public final class TypeUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBasicAttribute(Element element, Element returnedElement, Context context) {
|
public static boolean isBasicAttribute(Element element, Element returnedElement, Context context) {
|
||||||
return hasAnnotation( element, BASIC, ONE_TO_ONE, MANY_TO_ONE, EMBEDDED_ID, ID )
|
return hasAnnotation( element, BASIC, ONE_TO_ONE, MANY_TO_ONE, EMBEDDED, EMBEDDED_ID, ID )
|
||||||
|| hasAnnotation( element, "org.hibernate.annotations.Type") // METAGEN-28
|
|| hasAnnotation( element, "org.hibernate.annotations.Type") // METAGEN-28
|
||||||
|| returnedElement.asType().accept( new BasicAttributeVisitor( context ), returnedElement );
|
|| returnedElement.asType().accept( new BasicAttributeVisitor( context ), returnedElement );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue