diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractFinderMethod.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractFinderMethod.java index ff7dec4318..3e019fff74 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractFinderMethod.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AbstractFinderMethod.java @@ -8,13 +8,10 @@ package org.hibernate.jpamodelgen.annotation; import org.hibernate.internal.util.StringHelper; import org.hibernate.jpamodelgen.util.Constants; -import org.hibernate.query.Order; -import org.hibernate.query.SortDirection; import java.util.List; import java.util.Locale; -import static org.hibernate.jpamodelgen.util.Constants.JD_SORT; import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase; /** @@ -202,27 +199,7 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod { } @Override - boolean setOrder(StringBuilder declaration, boolean unwrapped, String paramName, String paramType) { - final boolean jakartaSort = paramType.startsWith(JD_SORT); - if ( jakartaSort ) { - annotationMetaEntity.staticImport(SortDirection.class.getName(), "ASCENDING"); - annotationMetaEntity.staticImport(SortDirection.class.getName(), "DESCENDING"); - declaration - .append("\n\t\t\t.setOrder(") - .append(annotationMetaEntity.importType(Order.class.getName())) - .append(".by(") - .append(annotationMetaEntity.importType(entity)) - .append(".class, ") - .append(paramName) - .append(".property()") - .append(",\n\t\t\t\t\t") - .append(paramName) - .append(".isAscending() ? ASCENDING : DESCENDING") - .append("))"); - return true; - } - else { - return super.setOrder(declaration, unwrapped, paramName, paramType); - } + String getSortableEntityClass() { + return entity; } } 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 06d2d40a98..ea392162fc 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 @@ -12,6 +12,7 @@ import org.hibernate.jpamodelgen.model.Metamodel; import org.hibernate.jpamodelgen.util.Constants; import org.hibernate.query.Order; import org.hibernate.query.Page; +import org.hibernate.query.SortDirection; import java.util.List; @@ -203,7 +204,31 @@ public abstract class AbstractQueryMethod implements MetaAttribute { boolean setOrder(StringBuilder declaration, boolean unwrapped, String paramName, String paramType) { unwrapQuery( declaration, unwrapped ); - if ( paramType.endsWith("...") ) { + final boolean jakartaSort = paramType.startsWith(JD_SORT); + if ( jakartaSort ) { + final String sortableEntityClass = getSortableEntityClass(); + if ( sortableEntityClass != null ) { + annotationMetaEntity.staticImport(SortDirection.class.getName(), "ASCENDING"); + annotationMetaEntity.staticImport(SortDirection.class.getName(), "DESCENDING"); + declaration + .append("\n\t\t\t.setOrder(") + .append(annotationMetaEntity.importType(Order.class.getName())) + .append(".by(") + .append(annotationMetaEntity.importType(sortableEntityClass)) + .append(".class, ") + .append(paramName) + .append(".property()") + .append(",\n\t\t\t\t\t") + .append(paramName) + .append(".isAscending() ? ASCENDING : DESCENDING") + .append("))"); + return true; + } + else { + return false; + } + } + else if ( paramType.endsWith("...") ) { declaration .append("\n\t\t\t.setOrder(") .append(annotationMetaEntity.importType(Constants.LIST)) @@ -220,6 +245,10 @@ public abstract class AbstractQueryMethod implements MetaAttribute { return true; } + @Nullable String getSortableEntityClass() { + return returnTypeName; + } + private void unwrapQuery(StringBuilder declaration, boolean unwrapped) { if ( !unwrapped ) { declaration 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 26efc4f2f3..4334e9ec6e 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 @@ -12,6 +12,7 @@ import org.hibernate.jpamodelgen.util.Constants; import java.util.List; import java.util.StringTokenizer; +import static org.hibernate.jpamodelgen.util.Constants.JD_SORT; import static org.hibernate.jpamodelgen.util.TypeUtils.isPrimitive; /** @@ -60,86 +61,18 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { parameters( paramTypes, declaration ); declaration .append(" {"); - for ( int i = 0; i< paramNames.size(); i++ ) { - final String paramName = paramNames.get(i); - final String paramType = paramTypes.get(i); - if ( !isNullable(i) && !isPrimitive(paramType) ) { - declaration - .append("\n\tif (") - .append(paramName) - .append(" == null) throw new IllegalArgumentException(\"Null \" + ") - .append(paramName) - .append(");"); - } - } - declaration - .append("\n\tvar builder = ") - .append(sessionName) - .append(isUsingEntityManager() - ? ".getEntityManagerFactory()" - : ".getFactory()") - .append(".getCriteriaBuilder();") - .append("\n\tvar query = builder.createQuery(") - .append(annotationMetaEntity.importType(entity)) - .append(".class);") - .append("\n\tvar entity = query.from(") - .append(annotationMetaEntity.importType(entity)) - .append(".class);") - .append("\n\tquery.where("); - boolean first = true; - for ( int i = 0; i < paramNames.size(); i ++ ) { - final String paramName = paramNames.get(i); - final String paramType = paramTypes.get(i); - if ( !isSessionParameter(paramType) - && !isPageParam(paramType) - && !isOrderParam(paramType) ) { - if ( first ) { - first = false; - } - else { - declaration - .append(", "); - } - parameter( declaration, i, paramName, paramType ); - } - } - declaration - .append("\n\t);"); - if ( !orderBys.isEmpty() ) { - declaration.append("\n\tquery.orderBy("); - boolean firstOrderBy = true; - for ( OrderBy orderBy : orderBys ) { - if ( firstOrderBy ) { - firstOrderBy = false; - } - else { - declaration.append(", "); - } - declaration - .append("builder.") - .append(orderBy.descending ? "desc" : "asc") - .append('('); - if ( orderBy.ignoreCase ) { - declaration.append("builder.lower("); - } - declaration - .append("entity.get(\"") - .append(orderBy.fieldName) - .append("\")"); - if ( orderBy.ignoreCase ) { - declaration - .append(')'); - } - declaration - .append(')'); - } - declaration.append(");"); - } + nullChecks(paramTypes, declaration); + + createQuery(declaration); + where(declaration, paramTypes); + orderBy(paramTypes, declaration); + declaration .append("\n\treturn ") .append(sessionName) .append(".createQuery(query)"); - final boolean hasOrderParameter = paramTypes.stream().anyMatch(AbstractQueryMethod::isOrderParam); + final boolean hasOrderParameter = + paramTypes.stream().anyMatch(AbstractQueryMethod::isOrderParam); final boolean hasEnabledFetchProfiles = !fetchProfiles.isEmpty(); final boolean hasNativeReturnType = containerType != null && containerType.startsWith("org.hibernate"); @@ -158,7 +91,7 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { if ( isPageParam(paramType) ) { setPage( declaration, paramName, paramType ); } - else if ( isOrderParam(paramType) ) { + else if ( isOrderParam(paramType) && !isJakartaSortParam(paramType) ) { setOrder( declaration, true, paramName, paramType ); } } @@ -182,6 +115,139 @@ public class CriteriaFinderMethod extends AbstractFinderMethod { return declaration.toString(); } + private void createQuery(StringBuilder declaration) { + declaration + .append("\n\tvar builder = ") + .append(sessionName) + .append(isUsingEntityManager() + ? ".getEntityManagerFactory()" + : ".getFactory()") + .append(".getCriteriaBuilder();") + .append("\n\tvar query = builder.createQuery(") + .append(annotationMetaEntity.importType(entity)) + .append(".class);") + .append("\n\tvar entity = query.from(") + .append(annotationMetaEntity.importType(entity)) + .append(".class);"); + } + + private void nullChecks(List paramTypes, StringBuilder declaration) { + for ( int i = 0; i< paramNames.size(); i++ ) { + final String paramName = paramNames.get(i); + final String paramType = paramTypes.get(i); + if ( !isNullable(i) && !isPrimitive(paramType) ) { + declaration + .append("\n\tif (") + .append(paramName) + .append(" == null) throw new IllegalArgumentException(\"Null \" + ") + .append(paramName) + .append(");"); + } + } + } + + private void orderBy(List paramTypes, StringBuilder declaration) { + final boolean hasSortParameter = + paramTypes.stream().anyMatch(CriteriaFinderMethod::isJakartaSortParam); + if ( !orderBys.isEmpty() || hasSortParameter ) { + declaration.append("\n\tquery.orderBy("); + } + boolean firstOrderBy = true; + if ( !orderBys.isEmpty() ) { + for ( OrderBy orderBy : orderBys ) { + if ( firstOrderBy ) { + firstOrderBy = false; + } + else { + declaration.append(','); + } + orderBy(declaration, orderBy); + } + } + if ( hasSortParameter ) { + for ( int i = 0; i < paramNames.size(); i ++ ) { + final String paramName = paramNames.get(i); + final String paramType = paramTypes.get(i); + if ( isJakartaSortParam(paramType) ) { + if ( firstOrderBy ) { + firstOrderBy = false; + } + else { + declaration.append(','); + } + orderBy(declaration, paramName); + } + } + } + if ( !orderBys.isEmpty() || hasSortParameter ) { + declaration.append("\n\t);"); + } + } + + private void where(StringBuilder declaration, List paramTypes) { + declaration + .append("\n\tquery.where("); + boolean first = true; + for ( int i = 0; i < paramNames.size(); i ++ ) { + final String paramName = paramNames.get(i); + final String paramType = paramTypes.get(i); + if ( !isSessionParameter(paramType) + && !isPageParam(paramType) + && !isOrderParam(paramType) ) { + if ( first ) { + first = false; + } + else { + declaration + .append(", "); + } + parameter(declaration, i, paramName, paramType ); + } + } + declaration + .append("\n\t);"); + } + + private static boolean isJakartaSortParam(String paramType) { + return paramType.startsWith(JD_SORT); + } + + private static void orderBy(StringBuilder declaration, OrderBy orderBy) { + declaration + .append("\n\t\t") + .append("builder.") + .append(orderBy.descending ? "desc" : "asc") + .append('('); + if ( orderBy.ignoreCase ) { + declaration.append("builder.lower("); + } + declaration + .append("entity.get(\"") + .append(orderBy.fieldName) + .append("\")"); + if ( orderBy.ignoreCase ) { + declaration + .append(')'); + } + declaration + .append(')'); + } + + private static void orderBy(StringBuilder declaration, String paramName) { + declaration + .append("\n\t\t") + .append(paramName) + .append(".isAscending()\n") + .append("\t\t\t\t? builder.") + .append("asc(entity.get(") + .append(paramName) + .append(".property()))\n") + .append("\t\t\t\t: builder.") + .append("desc(entity.get(") + .append(paramName) + .append(".property()))"); + } + private void parameter(StringBuilder declaration, int i, String paramName, String paramType) { declaration .append("\n\t\t\t"); 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 5e056b145b..af24f842c3 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 @@ -20,7 +20,6 @@ import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFr */ public class QueryMethod extends AbstractQueryMethod { private final String queryString; - private final @Nullable String returnTypeName; private final @Nullable String containerTypeName; private final boolean isUpdate; private final boolean isNative; @@ -47,7 +46,6 @@ public class QueryMethod extends AbstractQueryMethod { sessionType, sessionName, belongsToDao, addNonnullAnnotation ); this.queryString = queryString; - this.returnTypeName = returnTypeName; this.containerTypeName = containerTypeName; this.isUpdate = isUpdate; this.isNative = isNative;