Skip to content

Commit

Permalink
HHH-18649 more work on TypedQueryReference in static metamodel
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinking committed Sep 21, 2024
1 parent acf2af5 commit 3ef1801
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
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;
Expand Down Expand Up @@ -103,25 +107,56 @@ private void handleNamedQuery(AnnotationMirror mirror, boolean checkHql) {
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) == '#'
Expand Down Expand Up @@ -165,8 +200,9 @@ private void addAuxiliaryMembersForMirror(AnnotationMirror mirror, String prefix
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" );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public String getAttributeNameDeclarationString() {
.toString();
}

private String fieldName() {
String fieldName() {
return nameToFieldName(name.charAt(0) == '#' ? name.substring(1) : name);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* @author Gavin King
*/
class TypedMetaAttribute extends NameMetaAttribute {
private final String prefix;
private final String resultType;
private final String referenceType;

Expand All @@ -22,6 +23,7 @@ public TypedMetaAttribute(
String resultType,
String referenceType) {
super( annotationMetaEntity, name, prefix );
this.prefix = prefix;
this.resultType = resultType;
this.referenceType = referenceType;
}
Expand All @@ -34,8 +36,13 @@ public boolean hasTypedAttribute() {
@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 ")
Expand All @@ -45,8 +52,11 @@ public String getAttributeDeclarationString() {
.append('>')
.append(' ')
.append('_')
.append(nameToMethodName(getPropertyName()))
.append(';')
.toString();
.append(nameToMethodName(getPropertyName()));
if ( "QUERY_".equals(prefix) ) { //UGLY!
declaration.append('_');
}
declaration.append(';');
return declaration.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@

@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",
Expand Down

0 comments on commit 3ef1801

Please sign in to comment.