From 8794f86ad2b20749983fbaee2c37340ef3754186 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 23 Jul 2023 13:16:18 +0200 Subject: [PATCH] allow criteria-based @Find methods to specify Page and Order This is not necessary for @Id or @NaturalId-based @Find methods, because they don't return multiple results. --- .../annotation/AbstractQueryMethod.java | 57 ++++++++++++++++ .../annotation/AnnotationMetaEntity.java | 5 +- .../annotation/CriteriaFinderMethod.java | 67 ++++++++++++------- .../jpamodelgen/annotation/QueryMethod.java | 55 --------------- .../hibernate/jpamodelgen/test/dao/Dao.java | 5 ++ 5 files changed, 108 insertions(+), 81 deletions(-) diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractQueryMethod.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractQueryMethod.java index aa9a64bd12..ac5542720c 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractQueryMethod.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractQueryMethod.java @@ -10,6 +10,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.jpamodelgen.model.MetaAttribute; import org.hibernate.jpamodelgen.model.Metamodel; import org.hibernate.jpamodelgen.util.Constants; +import org.hibernate.query.Order; +import org.hibernate.query.Page; import java.util.List; @@ -159,4 +161,59 @@ public abstract class AbstractQueryMethod implements MetaAttribute { boolean isReactive() { return Constants.MUTINY_SESSION.equals(sessionType); } + + void setPage(StringBuilder declaration, String paramName) { + if ( isUsingEntityManager() ) { + declaration + .append("\n\t\t\t.setFirstResult(") + .append(paramName) + .append(".getFirstResult())") + .append("\n\t\t\t.setMaxResults(") + .append(paramName) + .append(".getMaxResults())"); + } + else { + declaration + .append("\n\t\t\t.setPage(") + .append(paramName) + .append(")"); + } + } + + boolean setOrder(StringBuilder declaration, boolean unwrapped, String paramName, String paramType) { + unwrapQuery( declaration, unwrapped ); + if ( paramType.endsWith("...") ) { + declaration + .append("\n\t\t\t.setOrder(") + .append(annotationMetaEntity.importType(Constants.LIST)) + .append(".of(") + .append(paramName) + .append("))"); + } + else { + declaration + .append("\n\t\t\t.setOrder(") + .append(paramName) + .append(")"); + } + return true; + } + + private void unwrapQuery(StringBuilder declaration, boolean unwrapped) { + if ( !unwrapped ) { + declaration + .append("\n\t\t\t.unwrap(") + .append(annotationMetaEntity.importType(Constants.HIB_SELECTION_QUERY)) + .append(".class)"); + } + } + + static boolean isPageParam(String parameterType) { + return Page.class.getName().equals(parameterType); + } + + static boolean isOrderParam(String parameterType) { + return parameterType.startsWith(Order.class.getName()) + || parameterType.startsWith(List.class.getName() + "<" + Order.class.getName()); + } } diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java index c5a4e5a507..3a2d5ecd1c 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java @@ -573,7 +573,10 @@ public class AnnotationMetaEntity extends AnnotationMeta { } private static boolean isFinderParameterMappingToAttribute(VariableElement param) { - return !isSessionParameter( param.asType().toString() ); + final String type = param.asType().toString(); + return !isSessionParameter( type ) + && !isPageParam( type ) + && !isOrderParam( type ); } private String[] sessionTypeFromParameters(List paramNames, List paramTypes) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/CriteriaFinderMethod.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/CriteriaFinderMethod.java index cceb204de6..c9fb8f171f 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/CriteriaFinderMethod.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/CriteriaFinderMethod.java @@ -86,7 +86,9 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { for ( int i = 0; i < paramNames.size(); i ++ ) { final String paramName = paramNames.get(i); final String paramType = paramTypes.get(i); - if ( !isSessionParameter(paramType) ) { + if ( !isSessionParameter(paramType) + && !isPageParam(paramType) + && !isOrderParam(paramType) ) { if ( first ) { first = false; } @@ -94,27 +96,7 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { declaration .append(", "); } - declaration - .append("\n\t\t\t"); - if ( isNullable(i) && !isPrimitive(paramType) ) { - declaration - .append(paramName) - .append("==null") - .append("\n\t\t\t\t? ") - .append("entity"); - path( declaration, paramName ); - declaration - .append(".isNull()") - .append("\n\t\t\t\t: "); - } - declaration - .append("builder.equal(entity"); - path( declaration, paramName ); - declaration - .append(", ") - //TODO: only safe if we are binding literals as parameters!!! - .append(paramName) - .append(')'); + parameter( declaration, i, paramName, paramType ); } } declaration @@ -122,11 +104,12 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { .append("\n\treturn ") .append(sessionName) .append(".createQuery(query)"); + final boolean hasOrderParameter = paramTypes.stream().anyMatch(AbstractQueryMethod::isOrderParam); final boolean hasEnabledFetchProfiles = !fetchProfiles.isEmpty(); final boolean hasNativeReturnType = containerType != null && containerType.startsWith("org.hibernate"); final boolean unwrap = - ( hasEnabledFetchProfiles || hasNativeReturnType ) + ( hasOrderParameter || hasEnabledFetchProfiles || hasNativeReturnType ) && isUsingEntityManager(); if ( unwrap ) { declaration @@ -134,16 +117,26 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { .append(annotationMetaEntity.importType(Constants.HIB_SELECTION_QUERY)) .append(".class)"); } + for ( int i = 0; i < paramNames.size(); i ++ ) { + final String paramName = paramNames.get(i); + final String paramType = paramTypes.get(i); + if ( isPageParam(paramType) ) { + setPage( declaration, paramName ); + } + else if ( isOrderParam(paramType) ) { + setOrder( declaration, true, paramName, paramType ); + } + } enableFetchProfile( declaration ); if ( containerType == null) { - if ( unwrap || hasEnabledFetchProfiles) { + if ( unwrap || hasEnabledFetchProfiles ) { declaration.append("\n\t\t\t"); } declaration .append(".getSingleResult()"); } else if ( containerType.equals(Constants.LIST) ) { - if ( unwrap || hasEnabledFetchProfiles ) { + if ( unwrap || hasOrderParameter || hasEnabledFetchProfiles ) { declaration.append("\n\t\t\t"); } declaration @@ -154,6 +147,30 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { return declaration.toString(); } + private void parameter(StringBuilder declaration, int i, String paramName, String paramType) { + declaration + .append("\n\t\t\t"); + if ( isNullable(i) && !isPrimitive(paramType) ) { + declaration + .append(paramName) + .append("==null") + .append("\n\t\t\t\t? ") + .append("entity"); + path( declaration, paramName ); + declaration + .append(".isNull()") + .append("\n\t\t\t\t: "); + } + declaration + .append("builder.equal(entity"); + path( declaration, paramName ); + declaration + .append(", ") + //TODO: only safe if we are binding literals as parameters!!! + .append(paramName) + .append(')'); + } + private void path(StringBuilder declaration, String paramName) { final StringTokenizer tokens = new StringTokenizer(paramName, "$"); String typeName = entity; diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/QueryMethod.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/QueryMethod.java index b7b2680ee0..fbd18d34f5 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/QueryMethod.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/QueryMethod.java @@ -183,43 +183,6 @@ public class QueryMethod extends AbstractQueryMethod { .append(")"); } - private void setPage(StringBuilder declaration, String paramName) { - if ( isUsingEntityManager() ) { - declaration - .append("\n\t\t\t.setFirstResult(") - .append(paramName) - .append(".getFirstResult())") - .append("\n\t\t\t.setMaxResults(") - .append(paramName) - .append(".getMaxResults())"); - } - else { - declaration - .append("\n\t\t\t.setPage(") - .append(paramName) - .append(")"); - } - } - - private boolean setOrder(StringBuilder declaration, boolean unwrapped, String paramName, String paramType) { - unwrap( declaration, unwrapped ); - if ( paramType.endsWith("...") ) { - declaration - .append("\n\t\t\t.setOrder(") - .append(annotationMetaEntity.importType(Constants.LIST)) - .append(".of(") - .append(paramName) - .append("))"); - } - else { - declaration - .append("\n\t\t\t.setOrder(") - .append(paramName) - .append(")"); - } - return true; - } - private StringBuilder returnType() { StringBuilder type = new StringBuilder(); boolean returnsUni = isReactive() @@ -283,24 +246,6 @@ public class QueryMethod extends AbstractQueryMethod { } } - static boolean isPageParam(String parameterType) { - return Page.class.getName().equals(parameterType); - } - - static boolean isOrderParam(String parameterType) { - return parameterType.startsWith(Order.class.getName()) - || parameterType.startsWith(List.class.getName() + "<" + Order.class.getName()); - } - - private void unwrap(StringBuilder declaration, boolean unwrapped) { - if ( !unwrapped ) { - declaration - .append("\n\t\t\t.unwrap(") - .append(annotationMetaEntity.importType(Constants.HIB_SELECTION_QUERY)) - .append(".class)"); - } - } - @Override public String getAttributeNameDeclarationString() { return new StringBuilder() diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/dao/Dao.java b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/dao/Dao.java index 080293f7b9..90b3c72cb8 100644 --- a/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/dao/Dao.java +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/jpamodelgen/test/dao/Dao.java @@ -5,6 +5,8 @@ import jakarta.persistence.TypedQuery; import org.hibernate.annotations.processing.Find; import org.hibernate.annotations.processing.HQL; import org.hibernate.annotations.processing.SQL; +import org.hibernate.query.Order; +import org.hibernate.query.Page; import org.hibernate.query.SelectionQuery; import java.util.List; @@ -34,6 +36,9 @@ public interface Dao { @Find(enabledFetchProfiles="Hello") List getBooksFetching(String title); + @Find + List getBooks(String title, Page page, Order order); + @Find SelectionQuery createBooksSelectionQuery(String title);