HHH-18649 more work on TypedQueryReference in static metamodel

This commit is contained in:
Gavin King 2024-09-21 13:45:55 +02:00
parent 79d3a3410d
commit 8b83a53678
4 changed files with 73 additions and 21 deletions

View File

@ -13,7 +13,11 @@ import org.hibernate.processor.model.Metamodel;
import org.hibernate.processor.util.Constants;
import org.hibernate.processor.validation.ProcessorSessionFactory;
import org.hibernate.processor.validation.Validation;
import org.hibernate.query.criteria.JpaEntityJoin;
import org.hibernate.query.criteria.JpaRoot;
import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.select.SqmSelectClause;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import javax.lang.model.element.AnnotationMirror;
@ -103,25 +107,56 @@ public abstract class AnnotationMeta implements Metamodel {
ProcessorSessionFactory.create( context.getProcessingEnvironment(),
context.getEntityNameMappings(), context.getEnumTypesByValue() )
);
if ( statement instanceof SqmSelectStatement
&& isQueryMethodName( name ) ) {
putMember( name,
new NamedQueryMethod(
this,
(SqmSelectStatement<?>) statement,
name.substring(1),
isRepository(),
getSessionType(),
getSessionVariableName(),
context.addNonnullAnnotation()
)
);
if ( statement instanceof SqmSelectStatement<?> selectStatement ) {
if ( isQueryMethodName( name ) ) {
putMember( name,
new NamedQueryMethod(
this,
selectStatement,
name.substring(1),
isRepository(),
getSessionType(),
getSessionVariableName(),
context.addNonnullAnnotation()
)
);
}
if ( !isJakartaDataStyle()
&& getAnnotationValue( mirror, "resultClass" ) == null ) {
final String resultType = resultType( selectStatement );
if ( resultType != null ) {
putMember( "QUERY_" + name,
new TypedMetaAttribute( this, name, "QUERY_", resultType,
"jakarta.persistence.TypedQueryReference" ) );
}
}
}
}
}
}
}
private static @Nullable String resultType(SqmSelectStatement<?> selectStatement) {
final JpaSelection<?> selection = selectStatement.getSelection();
if (selection == null) {
return null;
}
else if (selection instanceof SqmSelectClause from) {
return from.getSelectionItems().size() > 1
? "Object[]"
: from.getSelectionItems().get(0).getJavaTypeName();
}
else if (selection instanceof JpaRoot<?> root) {
return root.getModel().getTypeName();
}
else if (selection instanceof JpaEntityJoin<?, ?> join) {
return join.getModel().getTypeName();
}
else {
return selection.getJavaTypeName();
}
}
private static boolean isQueryMethodName(String name) {
return name.length() >= 2
&& name.charAt(0) == '#'
@ -165,8 +200,9 @@ public abstract class AnnotationMeta implements Metamodel {
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)
// if there is no explicit result class, we will infer it later by
// type checking the query (this is allowed but not required by JPA)
// and then we will replace this TypedMetaAttribute
return new TypedMetaAttribute( this, name, prefix,
resultClass == null ? JAVA_OBJECT : resultClass.getValue().toString(),
"jakarta.persistence.TypedQueryReference" );

View File

@ -54,7 +54,7 @@ class NameMetaAttribute implements MetaAttribute {
.toString();
}
private String fieldName() {
String fieldName() {
return nameToFieldName(name.charAt(0) == '#' ? name.substring(1) : name);
}

View File

@ -12,6 +12,7 @@ import static org.hibernate.processor.util.StringUtil.nameToMethodName;
* @author Gavin King
*/
class TypedMetaAttribute extends NameMetaAttribute {
private final String prefix;
private final String resultType;
private final String referenceType;
@ -22,6 +23,7 @@ class TypedMetaAttribute extends NameMetaAttribute {
String resultType,
String referenceType) {
super( annotationMetaEntity, name, prefix );
this.prefix = prefix;
this.resultType = resultType;
this.referenceType = referenceType;
}
@ -34,8 +36,13 @@ class TypedMetaAttribute extends NameMetaAttribute {
@Override
public String getAttributeDeclarationString() {
final Metamodel entity = getHostingEntity();
return new StringBuilder()
.append("\n/**\n * @see ")
final StringBuilder declaration = new StringBuilder();
declaration
.append("\n/**")
.append("\n * The query named {@value ")
.append(prefix)
.append(fieldName())
.append("}\n *\n * @see ")
.append(entity.getQualifiedName())
.append("\n **/\n")
.append("public static volatile ")
@ -45,8 +52,11 @@ class TypedMetaAttribute extends NameMetaAttribute {
.append('>')
.append(' ')
.append('_')
.append(nameToMethodName(getPropertyName()))
.append(';')
.toString();
.append(nameToMethodName(getPropertyName()));
if ( "QUERY_".equals(prefix) ) { //UGLY!
declaration.append('_');
}
declaration.append(';');
return declaration.toString();
}
}

View File

@ -11,6 +11,12 @@ import jakarta.persistence.NamedQuery;
@Entity
@NamedEntityGraph(name = "entityGraph")
@NamedQuery(name="booksByTitle",
query = "from Book where title = ?1")
@NamedQuery(name="booksByTitleVerbose",
query = "select book from Book book where book.title = ?1")
@NamedQuery(name = "titlesWithIsbns",
query = "select title, isbn from Book")
@NamedQuery(name = "#findByTitle",
query = "from Book where title like :titlePattern")
@NamedQuery(name = "#findByTitleAndType",