HHH-18649 TypedQueryReference and EntityGraph in static metamodel

This commit is contained in:
Gavin King 2024-09-21 12:17:20 +02:00
parent d53498910a
commit e13efce86b
5 changed files with 101 additions and 31 deletions

View File

@ -376,8 +376,7 @@ public class HibernateProcessor extends AbstractProcessor {
context.logMessage( Diagnostic.Kind.OTHER, "Processing annotated class '" + element + "'" );
handleRootElementAuxiliaryAnnotationMirrors( element );
}
else if ( element instanceof TypeElement ) {
final TypeElement typeElement = (TypeElement) element;
else if ( element instanceof TypeElement typeElement ) {
final AnnotationMirror repository = getAnnotationMirror( element, JD_REPOSITORY );
if ( repository != null ) {
final AnnotationValue provider = getAnnotationValue( repository, "provider" );

View File

@ -21,6 +21,9 @@ import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import java.util.List;
import static java.lang.Character.isJavaIdentifierStart;
import static org.hibernate.processor.util.Constants.JAVA_OBJECT;
import static org.hibernate.processor.util.Constants.NAMED_QUERY;
import static org.hibernate.processor.util.TypeUtils.containsAnnotation;
import static org.hibernate.processor.util.TypeUtils.getAnnotationMirror;
import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
@ -28,7 +31,7 @@ import static org.hibernate.processor.util.TypeUtils.getAnnotationValue;
public abstract class AnnotationMeta implements Metamodel {
void addAuxiliaryMembers() {
addAuxiliaryMembersForAnnotation( Constants.NAMED_QUERY, "QUERY_" );
addAuxiliaryMembersForAnnotation( NAMED_QUERY, "QUERY_" );
addAuxiliaryMembersForRepeatableAnnotation( Constants.NAMED_QUERIES, "QUERY_" );
addAuxiliaryMembersForAnnotation( Constants.NAMED_NATIVE_QUERY, "QUERY_" );
addAuxiliaryMembersForRepeatableAnnotation( Constants.NAMED_NATIVE_QUERIES, "QUERY_" );
@ -50,7 +53,7 @@ public abstract class AnnotationMeta implements Metamodel {
void checkNamedQueries() {
boolean checkHql = containsAnnotation( getElement(), Constants.CHECK_HQL )
|| containsAnnotation( getElement().getEnclosingElement(), Constants.CHECK_HQL );
handleNamedQueryAnnotation( Constants.NAMED_QUERY, checkHql );
handleNamedQueryAnnotation( NAMED_QUERY, checkHql );
handleNamedQueryRepeatableAnnotation( Constants.NAMED_QUERIES, checkHql );
handleNamedQueryAnnotation( Constants.HIB_NAMED_QUERY, checkHql );
handleNamedQueryRepeatableAnnotation( Constants.HIB_NAMED_QUERIES, checkHql );
@ -86,9 +89,7 @@ public abstract class AnnotationMeta implements Metamodel {
final boolean reportErrors = context.checkNamedQuery( name );
final AnnotationValue value = getAnnotationValue( mirror, "query" );
if ( value != null ) {
final Object query = value.getValue();
if ( query instanceof String ) {
final String hql = (String) query;
if ( value.getValue() instanceof String hql ) {
final SqmStatement<?> statement =
Validation.validate(
hql,
@ -124,7 +125,7 @@ public abstract class AnnotationMeta implements Metamodel {
private static boolean isQueryMethodName(String name) {
return name.length() >= 2
&& name.charAt(0) == '#'
&& Character.isJavaIdentifierStart( name.charAt(1) )
&& isJavaIdentifierStart( name.charAt(1) )
&& name.substring(2).chars().allMatch(Character::isJavaIdentifierPart);
}
@ -155,13 +156,30 @@ public abstract class AnnotationMeta implements Metamodel {
if ( key.getSimpleName().contentEquals("name") ) {
final String name = value.getValue().toString();
if ( !name.isEmpty() ) {
putMember( prefix + name,
new NameMetaAttribute( this, name, prefix ) );
putMember( prefix + name, auxiliaryMember( mirror, prefix, name ) );
}
}
});
}
private NameMetaAttribute auxiliaryMember(AnnotationMirror mirror, String prefix, String name) {
if ( !isJakartaDataStyle() && "QUERY_".equals(prefix) ) {
final AnnotationValue resultClass = getAnnotationValue( mirror, "resultClass" );
//TODO: if there is no explicit result class, obtain the result class by
// type-checking the query (this is allowed but not required by JPA)
return new TypedMetaAttribute( this, name, prefix,
resultClass == null ? JAVA_OBJECT : resultClass.getValue().toString(),
"jakarta.persistence.TypedQueryReference" );
}
else if ( !isJakartaDataStyle() && "GRAPH_".equals(prefix) ) {
return new TypedMetaAttribute( this, name, prefix, getQualifiedName(),
"jakarta.persistence.EntityGraph" );
}
else {
return new NameMetaAttribute( this, name, prefix);
}
}
protected String getSessionVariableName() {
return "entityManager";
}

View File

@ -45,19 +45,20 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute {
public String getAttributeDeclarationString() {
return new StringBuilder()
.append("\n/**\n * @see ")
.append( parent.getQualifiedName() )
.append( "#")
.append( element.getSimpleName() )
.append( "\n **/\n" )
.append( "public static volatile " )
.append( parent.importType( getMetaType() ) )
.append( "<" )
.append( parent.importType( parent.getQualifiedName() ) )
.append( ", " )
.append( parent.importType( getTypeDeclaration() ) )
.append( "> " )
.append( getPropertyName() )
.append( ";" )
.append(parent.getQualifiedName())
.append('#')
.append(element.getSimpleName())
.append("\n **/\n")
.append("public static volatile ")
.append(parent.importType(getMetaType()))
.append('<')
.append(parent.importType(parent.getQualifiedName()))
.append(", ")
.append(parent.importType(getTypeDeclaration()))
.append('>')
.append(' ')
.append(getPropertyName())
.append(';')
.toString();
}
@ -66,13 +67,13 @@ public abstract class AnnotationMetaAttribute implements MetaAttribute {
return new StringBuilder()
.append("public static final ")
.append(parent.importType(String.class.getName()))
.append(" ")
.append(' ')
.append(getUpperUnderscoreCaseFromLowerCamelCase(getPropertyName()))
.append(" = ")
.append("\"")
.append('"')
.append(getPropertyName())
.append("\"")
.append(";")
.append('"')
.append(';')
.toString();
}

View File

@ -43,14 +43,14 @@ class NameMetaAttribute implements MetaAttribute {
return new StringBuilder()
.append("public static final ")
.append(annotationMetaEntity.importType(String.class.getName()))
.append(" ")
.append(' ')
.append(prefix)
.append(fieldName())
.append(" = ")
.append("\"")
.append('"')
.append(name)
.append("\"")
.append(";")
.append('"')
.append(';')
.toString();
}

View File

@ -0,0 +1,52 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.processor.annotation;
import org.hibernate.processor.model.Metamodel;
import static org.hibernate.processor.util.StringUtil.nameToMethodName;
/**
* @author Gavin King
*/
class TypedMetaAttribute extends NameMetaAttribute {
private final String resultType;
private final String referenceType;
public TypedMetaAttribute(
Metamodel annotationMetaEntity,
String name,
String prefix,
String resultType,
String referenceType) {
super( annotationMetaEntity, name, prefix );
this.resultType = resultType;
this.referenceType = referenceType;
}
@Override
public boolean hasTypedAttribute() {
return true;
}
@Override
public String getAttributeDeclarationString() {
final Metamodel entity = getHostingEntity();
return new StringBuilder()
.append("\n/**\n * @see ")
.append(entity.getQualifiedName())
.append("\n **/\n")
.append("public static volatile ")
.append(entity.importType(referenceType))
.append('<')
.append(entity.importType(resultType))
.append('>')
.append(' ')
.append('_')
.append(nameToMethodName(getPropertyName()))
.append(';')
.toString();
}
}