HHH-17772 better support for Sort

This commit is contained in:
Gavin King 2024-02-23 15:39:00 +01:00
parent bd63c4af50
commit 7a52cf9659
4 changed files with 175 additions and 105 deletions

View File

@ -8,13 +8,10 @@ package org.hibernate.jpamodelgen.annotation;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpamodelgen.util.Constants; import org.hibernate.jpamodelgen.util.Constants;
import org.hibernate.query.Order;
import org.hibernate.query.SortDirection;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import static org.hibernate.jpamodelgen.util.Constants.JD_SORT;
import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase; import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase;
/** /**
@ -202,27 +199,7 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
} }
@Override @Override
boolean setOrder(StringBuilder declaration, boolean unwrapped, String paramName, String paramType) { String getSortableEntityClass() {
final boolean jakartaSort = paramType.startsWith(JD_SORT); return entity;
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);
}
} }
} }

View File

@ -12,6 +12,7 @@ import org.hibernate.jpamodelgen.model.Metamodel;
import org.hibernate.jpamodelgen.util.Constants; import org.hibernate.jpamodelgen.util.Constants;
import org.hibernate.query.Order; import org.hibernate.query.Order;
import org.hibernate.query.Page; import org.hibernate.query.Page;
import org.hibernate.query.SortDirection;
import java.util.List; import java.util.List;
@ -203,7 +204,31 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
boolean setOrder(StringBuilder declaration, boolean unwrapped, String paramName, String paramType) { boolean setOrder(StringBuilder declaration, boolean unwrapped, String paramName, String paramType) {
unwrapQuery( declaration, unwrapped ); 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 declaration
.append("\n\t\t\t.setOrder(") .append("\n\t\t\t.setOrder(")
.append(annotationMetaEntity.importType(Constants.LIST)) .append(annotationMetaEntity.importType(Constants.LIST))
@ -220,6 +245,10 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
return true; return true;
} }
@Nullable String getSortableEntityClass() {
return returnTypeName;
}
private void unwrapQuery(StringBuilder declaration, boolean unwrapped) { private void unwrapQuery(StringBuilder declaration, boolean unwrapped) {
if ( !unwrapped ) { if ( !unwrapped ) {
declaration declaration

View File

@ -12,6 +12,7 @@ import org.hibernate.jpamodelgen.util.Constants;
import java.util.List; import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import static org.hibernate.jpamodelgen.util.Constants.JD_SORT;
import static org.hibernate.jpamodelgen.util.TypeUtils.isPrimitive; import static org.hibernate.jpamodelgen.util.TypeUtils.isPrimitive;
/** /**
@ -60,86 +61,18 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
parameters( paramTypes, declaration ); parameters( paramTypes, declaration );
declaration declaration
.append(" {"); .append(" {");
for ( int i = 0; i< paramNames.size(); i++ ) { nullChecks(paramTypes, declaration);
final String paramName = paramNames.get(i);
final String paramType = paramTypes.get(i); createQuery(declaration);
if ( !isNullable(i) && !isPrimitive(paramType) ) { where(declaration, paramTypes);
declaration orderBy(paramTypes, 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(");");
}
declaration declaration
.append("\n\treturn ") .append("\n\treturn ")
.append(sessionName) .append(sessionName)
.append(".createQuery(query)"); .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 hasEnabledFetchProfiles = !fetchProfiles.isEmpty();
final boolean hasNativeReturnType = final boolean hasNativeReturnType =
containerType != null && containerType.startsWith("org.hibernate"); containerType != null && containerType.startsWith("org.hibernate");
@ -158,7 +91,7 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
if ( isPageParam(paramType) ) { if ( isPageParam(paramType) ) {
setPage( declaration, paramName, paramType ); setPage( declaration, paramName, paramType );
} }
else if ( isOrderParam(paramType) ) { else if ( isOrderParam(paramType) && !isJakartaSortParam(paramType) ) {
setOrder( declaration, true, paramName, paramType ); setOrder( declaration, true, paramName, paramType );
} }
} }
@ -182,6 +115,139 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
return declaration.toString(); 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<String> 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<String> 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<String> 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) { private void parameter(StringBuilder declaration, int i, String paramName, String paramType) {
declaration declaration
.append("\n\t\t\t"); .append("\n\t\t\t");

View File

@ -20,7 +20,6 @@ import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFr
*/ */
public class QueryMethod extends AbstractQueryMethod { public class QueryMethod extends AbstractQueryMethod {
private final String queryString; private final String queryString;
private final @Nullable String returnTypeName;
private final @Nullable String containerTypeName; private final @Nullable String containerTypeName;
private final boolean isUpdate; private final boolean isUpdate;
private final boolean isNative; private final boolean isNative;
@ -47,7 +46,6 @@ public class QueryMethod extends AbstractQueryMethod {
sessionType, sessionName, sessionType, sessionName,
belongsToDao, addNonnullAnnotation ); belongsToDao, addNonnullAnnotation );
this.queryString = queryString; this.queryString = queryString;
this.returnTypeName = returnTypeName;
this.containerTypeName = containerTypeName; this.containerTypeName = containerTypeName;
this.isUpdate = isUpdate; this.isUpdate = isUpdate;
this.isNative = isNative; this.isNative = isNative;