HHH-17772 support KeysetAwareSlice from Jakarta Data

significant refactoring
This commit is contained in:
Gavin King 2024-02-28 21:11:04 +01:00
parent 6f00449af1
commit 9e5ce60ac1
10 changed files with 360 additions and 203 deletions

View File

@ -12,6 +12,7 @@ import org.hibernate.jpamodelgen.util.Constants;
import java.util.List;
import java.util.Locale;
import static org.hibernate.jpamodelgen.util.Constants.HIB_SESSION;
import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase;
/**
@ -146,24 +147,23 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
if ( isUsingEntityManager() ) {
declaration
.append(".unwrap(")
.append(annotationMetaEntity.importType(Constants.HIB_SESSION))
.append(annotationMetaEntity.importType(HIB_SESSION))
.append(".class)\n\t\t\t");
}
}
void enableFetchProfile(StringBuilder declaration) {
// if ( !usingEntityManager ) {
// declaration
// .append("\n\t\t\t.enableFetchProfile(")
// .append(constantName())
// .append(")");
// }
boolean enableFetchProfile(StringBuilder declaration, boolean unwrapped) {
if ( !fetchProfiles.isEmpty() ) {
unwrapQuery( declaration, unwrapped );
unwrapped = true;
}
for ( String profile : fetchProfiles ) {
declaration
.append("\n\t\t\t.enableFetchProfile(")
.append(profile)
.append(")");
}
return unwrapped;
}
void preamble(StringBuilder declaration) {

View File

@ -7,13 +7,13 @@
package org.hibernate.jpamodelgen.annotation;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.AssertionFailure;
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.SortDirection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -23,12 +23,16 @@ import static org.hibernate.jpamodelgen.util.Constants.HIB_KEYED_PAGE;
import static org.hibernate.jpamodelgen.util.Constants.HIB_KEYED_RESULT_LIST;
import static org.hibernate.jpamodelgen.util.Constants.HIB_ORDER;
import static org.hibernate.jpamodelgen.util.Constants.HIB_PAGE;
import static org.hibernate.jpamodelgen.util.Constants.HIB_SELECTION_QUERY;
import static org.hibernate.jpamodelgen.util.Constants.JD_KEYED_SLICE;
import static org.hibernate.jpamodelgen.util.Constants.JD_LIMIT;
import static org.hibernate.jpamodelgen.util.Constants.JD_ORDER;
import static org.hibernate.jpamodelgen.util.Constants.JD_PAGE_REQUEST;
import static org.hibernate.jpamodelgen.util.Constants.JD_SORT;
import static org.hibernate.jpamodelgen.util.Constants.LIST;
import static org.hibernate.jpamodelgen.util.Constants.OPTIONAL;
import static org.hibernate.jpamodelgen.util.Constants.SESSION_TYPES;
import static org.hibernate.jpamodelgen.util.Constants.STREAM;
import static org.hibernate.jpamodelgen.util.TypeUtils.isPrimitive;
/**
@ -231,18 +235,19 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
annotationMetaEntity.staticImport(Collectors.class.getName(), "toList");
annotationMetaEntity.staticImport(Order.class.getName(), "by");
declaration
.append("\n\t\t\t.setOrder(new ")
.append(annotationMetaEntity.importType(ArrayList.class.getName()))
.append("<>() {{\n\t\t\t\t")
.append("\n\t\t\t.setOrder(")
.append(paramName)
.append(".forEach(_sort -> add(")
.append("by(")
.append(".sorts().stream()")
.append("\n\t\t\t\t\t")
.append(".map(_sort -> by(")
.append(annotationMetaEntity.importType(sortableEntityClass))
.append(".class, ")
.append("_sort.property()")
.append(",\n\t\t\t\t\t\t")
.append("_sort.isAscending() ? ASCENDING : DESCENDING, ")
.append("_sort.ignoreCase())));\n\t\t\t}})");
.append(".class, _sort.property(),")
.append("\n\t\t\t\t\t\t\t")
.append("_sort.isAscending() ? ASCENDING : DESCENDING,")
.append("\n\t\t\t\t\t\t\t")
.append("_sort.ignoreCase()))")
.append("\n\t\t\t\t\t")
.append(".collect(toList()))");
}
}
else if ( paramType.startsWith(JD_SORT) && paramType.endsWith("...") ) {
@ -345,10 +350,22 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
}
void unwrapQuery(StringBuilder declaration, boolean unwrapped) {
if ( !unwrapped ) {
if ( !unwrapped && isUsingEntityManager() ) {
declaration
.append("\n\t\t\t.unwrap(")
.append(annotationMetaEntity.importType(Constants.HIB_SELECTION_QUERY))
.append("\n\t\t\t.unwrap(");
final String selectionQuery = annotationMetaEntity.importType(HIB_SELECTION_QUERY);
// final String className = getSortableEntityClass();
// if ( className != null ) {
// final String entityClass = annotationMetaEntity.importType(className);
// declaration
// .append("(Class<")
// .append(selectionQuery)
// .append("<")
// .append(entityClass)
// .append(">>) (Class) ");
// }
declaration
.append(selectionQuery)
.append(".class)");
}
}
@ -361,11 +378,13 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
}
static boolean isKeyedPageParam(String parameterType) {
return parameterType.startsWith(HIB_KEYED_PAGE);
return parameterType.startsWith(HIB_KEYED_PAGE)
|| parameterType.startsWith(JD_PAGE_REQUEST);
}
static boolean isKeyedResultList(String returnType) {
return returnType.startsWith(HIB_KEYED_RESULT_LIST);
return returnType.startsWith(HIB_KEYED_RESULT_LIST)
|| returnType.startsWith(JD_KEYED_SLICE);
}
static boolean isPageParam(String parameterType) {
@ -380,4 +399,120 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|| parameterType.startsWith(JD_SORT)
|| parameterType.startsWith(JD_ORDER);
}
void makeKeyedPage(StringBuilder declaration, List<String> paramTypes) {
annotationMetaEntity.importType("org.hibernate.query.Page");
annotationMetaEntity.importType("jakarta.data.page.impl.KeysetAwareSliceRecord");
annotationMetaEntity.importType("jakarta.data.page.PageRequest.Cursor");
annotationMetaEntity.staticImport("org.hibernate.query.KeyedPage.KeyInterpretation", "*");
for (int i = 0; i < paramTypes.size(); i++) {
if ( isKeyedPageParam( paramTypes.get(i) ) ) {
declaration
.append(MAKE_KEYED_PAGE.replace("pageRequest", paramNames.get(i)))
.append("\t\tvar results = ");
}
}
}
static final String MAKE_KEYED_SLICE
= "\t\tvar cursors =\n" +
"\t\t\t\tresults.getKeyList()\n" +
"\t\t\t\t\t\t.stream()\n" +
"\t\t\t\t\t\t.map(_key -> Cursor.forKeyset(_key.toArray()))\n" +
"\t\t\t\t\t\t.collect(toList());\n" +
"\t\tvar page =\n" +
"\t\t\t\tPageRequest.of(Entity.class)\n" +
"\t\t\t\t\t\t.sortBy(pageRequest.sorts())\n" +
"\t\t\t\t\t\t.size(pageRequest.size())\n" +
"\t\t\t\t\t\t.page(pageRequest.page() + 1);\n" +
"\t\treturn new KeysetAwareSliceRecord<>( results.getResultList(), cursors, pageRequest,\n" +
"\t\t\t\tresults.isLastPage() ? null : page.afterKeyset( results.getNextPage().getKey().toArray() ),\n" +
"\t\t\t\tresults.isFirstPage() ? null : page.beforeKeyset( results.getPreviousPage().getKey().toArray() ) );\n";
static final String MAKE_KEYED_PAGE
= "\t\tvar unkeyedPage =\n" +
"\t\t\t\tPage.page(pageRequest.size(), (int) pageRequest.page()-1)\n" +
"\t\t\t\t\t\t.keyedBy(pageRequest.sorts().stream()\n" +
"\t\t\t\t\t\t\t\t.map(_sort -> by(Book.class, _sort.property(),\n" +
"\t\t\t\t\t\t\t\t\t\t_sort.isAscending() ? ASCENDING : DESCENDING,\n" +
"\t\t\t\t\t\t\t\t\t\t_sort.ignoreCase())).collect(toList()));\n" +
"\t\tvar keyedPage =\n" +
"\t\t\t\tpageRequest.cursor()\n" +
"\t\t\t\t\t\t.map(_cursor -> {\n" +
"\t\t\t\t\t\t\t@SuppressWarnings(\"unchecked\")\n" +
"\t\t\t\t\t\t\tvar elements = (List<Comparable<?>>) _cursor.elements();\n" +
"\t\t\t\t\t\t\treturn switch ( pageRequest.mode() ) {\n" +
"\t\t\t\t\t\t\t\tcase CURSOR_NEXT -> unkeyedPage.withKey(elements, KEY_OF_LAST_ON_PREVIOUS_PAGE);\n" +
"\t\t\t\t\t\t\t\tcase CURSOR_PREVIOUS -> unkeyedPage.withKey(elements, KEY_OF_FIRST_ON_NEXT_PAGE);\n" +
"\t\t\t\t\t\t\t\tdefault -> unkeyedPage;\n" +
"\t\t\t\t\t\t\t};\n" +
"\t\t\t\t\t\t}).orElse(unkeyedPage);\n";
protected void executeSelect(
StringBuilder declaration,
List<String> paramTypes,
@Nullable String containerType,
boolean unwrapped,
boolean mustUnwrap) {
if ( containerType == null ) {
declaration
.append(".getSingleResult();");
}
else {
switch (containerType) {
case OPTIONAL:
declaration
.append(".uniqueResultOptional();");
break;
case STREAM:
declaration
.append(".getResultStream();");
break;
case LIST:
declaration
.append(".getResultList();");
break;
case HIB_KEYED_RESULT_LIST:
for (int i = 0; i < paramTypes.size(); i++) {
if ( isKeyedPageParam( paramTypes.get(i) ) ) {
declaration
.append(".getKeyedResultList(")
.append(paramNames.get(i))
.append(");");
}
}
break;
case JD_KEYED_SLICE:
for (int i = 0; i < paramTypes.size(); i++) {
if ( isKeyedPageParam( paramTypes.get(i) ) ) {
final String entityClass = getSortableEntityClass();
if ( entityClass == null ) {
throw new AssertionFailure("entity class cannot be null");
}
else {
final String entity = annotationMetaEntity.importType(entityClass);
declaration
.append("\t\t\t.getKeyedResultList(keyedPage);\n")
.append(MAKE_KEYED_SLICE
.replace("pageRequest", paramNames.get(i))
.replace("Entity", entity));
}
}
}
break;
default:
if ( isUsingEntityManager() && !unwrapped && mustUnwrap ) {
declaration
.append("\n\t\t\t")
.append(".unwrap(")
.append(annotationMetaEntity.importType(containerType))
.append(".class);");
}
else {
declaration.append(';');
}
}
}
}
}

View File

@ -53,6 +53,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
@ -69,25 +70,7 @@ import static org.hibernate.jpamodelgen.annotation.AbstractQueryMethod.isSession
import static org.hibernate.jpamodelgen.annotation.AbstractQueryMethod.isSpecialParam;
import static org.hibernate.jpamodelgen.annotation.QueryMethod.isOrderParam;
import static org.hibernate.jpamodelgen.annotation.QueryMethod.isPageParam;
import static org.hibernate.jpamodelgen.util.Constants.FIND;
import static org.hibernate.jpamodelgen.util.Constants.HIB_ORDER;
import static org.hibernate.jpamodelgen.util.Constants.HIB_SESSION;
import static org.hibernate.jpamodelgen.util.Constants.HIB_STATELESS_SESSION;
import static org.hibernate.jpamodelgen.util.Constants.HQL;
import static org.hibernate.jpamodelgen.util.Constants.ITERABLE;
import static org.hibernate.jpamodelgen.util.Constants.JD_DELETE;
import static org.hibernate.jpamodelgen.util.Constants.JD_FIND;
import static org.hibernate.jpamodelgen.util.Constants.JD_INSERT;
import static org.hibernate.jpamodelgen.util.Constants.JD_ORDER;
import static org.hibernate.jpamodelgen.util.Constants.JD_PAGE_REQUEST;
import static org.hibernate.jpamodelgen.util.Constants.JD_QUERY;
import static org.hibernate.jpamodelgen.util.Constants.JD_REPOSITORY;
import static org.hibernate.jpamodelgen.util.Constants.JD_SAVE;
import static org.hibernate.jpamodelgen.util.Constants.JD_SORT;
import static org.hibernate.jpamodelgen.util.Constants.JD_UPDATE;
import static org.hibernate.jpamodelgen.util.Constants.LIST;
import static org.hibernate.jpamodelgen.util.Constants.MUTINY_SESSION;
import static org.hibernate.jpamodelgen.util.Constants.SQL;
import static org.hibernate.jpamodelgen.util.Constants.*;
import static org.hibernate.jpamodelgen.util.NullnessUtil.castNonNull;
import static org.hibernate.jpamodelgen.util.TypeUtils.containsAnnotation;
import static org.hibernate.jpamodelgen.util.TypeUtils.determineAccessTypeForHierarchy;
@ -637,21 +620,19 @@ public class AnnotationMetaEntity extends AnnotationMeta {
}
private static boolean isLegalRawResultType(String containerTypeName) {
return containerTypeName.equals(Constants.LIST)
|| containerTypeName.equals(Constants.QUERY)
|| containerTypeName.equals(Constants.HIB_QUERY);
return LEGAL_RAW_RESULT_TYPES.contains( containerTypeName );
}
private static boolean isLegalGenericResultType(String containerTypeName) {
return containerTypeName.equals(Constants.LIST)
|| containerTypeName.equals(Constants.STREAM)
|| containerTypeName.equals(Constants.OPTIONAL)
|| containerTypeName.equals(Constants.TYPED_QUERY)
|| containerTypeName.equals(Constants.HIB_QUERY)
|| containerTypeName.equals(Constants.HIB_SELECTION_QUERY)
|| containerTypeName.equals(Constants.HIB_KEYED_RESULT_LIST);
return LEGAL_GENERIC_RESULT_TYPES.contains( containerTypeName );
}
private static final Set<String> LEGAL_RAW_RESULT_TYPES
= Set.of(LIST, QUERY, HIB_QUERY);
private static final Set<String> LEGAL_GENERIC_RESULT_TYPES
= Set.of(LIST, STREAM, OPTIONAL, TYPED_QUERY, HIB_QUERY, HIB_SELECTION_QUERY, HIB_KEYED_RESULT_LIST, JD_KEYED_SLICE);
private void addQueryMethod(
ExecutableElement method,
@Nullable TypeMirror returnType,

View File

@ -15,12 +15,10 @@ import java.util.List;
import java.util.StringTokenizer;
import java.util.stream.Collectors;
import static org.hibernate.jpamodelgen.util.Constants.HIB_KEYED_RESULT_LIST;
import static org.hibernate.jpamodelgen.util.Constants.HIB_SELECTION_QUERY;
import static org.hibernate.jpamodelgen.util.Constants.JD_KEYED_SLICE;
import static org.hibernate.jpamodelgen.util.Constants.JD_SORT;
import static org.hibernate.jpamodelgen.util.Constants.LIST;
import static org.hibernate.jpamodelgen.util.Constants.OPTIONAL;
import static org.hibernate.jpamodelgen.util.Constants.STREAM;
import static org.hibernate.jpamodelgen.util.TypeUtils.isPrimitive;
/**
@ -71,7 +69,7 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
modifiers( declaration );
preamble( declaration, paramTypes );
nullChecks( paramTypes, declaration );
createQuery( declaration );
createCriteriaQuery( declaration );
where( declaration, paramTypes );
orderBy( paramTypes, declaration );
executeQuery( declaration, paramTypes );
@ -93,87 +91,95 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
private void executeQuery(StringBuilder declaration, List<String> paramTypes) {
declaration
.append('\n');
if (dataRepository) {
tryReturn( declaration, paramTypes );
castResult( declaration );
createQuery( declaration );
boolean unwrapped = specialNeeds( declaration, paramTypes );
execute( declaration, paramTypes, unwrapped );
}
private void castResult(StringBuilder declaration) {
if ( containerType == null && !fetchProfiles.isEmpty()
&& isUsingEntityManager() ) {
declaration
.append("\ttry {\n\t");
.append("(")
.append(annotationMetaEntity.importType(entity))
.append(") ");
}
}
private boolean specialNeeds(StringBuilder declaration, List<String> paramTypes) {
boolean unwrapped = !isUsingEntityManager();
unwrapped = handleSpecialParameters( declaration, paramTypes, unwrapped );
unwrapped = enableFetchProfile( declaration, unwrapped );
unwrapped = unwrapIfOptional( declaration, unwrapped );
if ( unwrapped ) {
declaration.append("\n\t\t\t");
}
return unwrapped;
}
private boolean unwrapIfOptional(StringBuilder declaration, boolean unwrapped) {
if ( OPTIONAL.equals(containerType) ) {
unwrapQuery(declaration, unwrapped);
unwrapped = true;
}
return unwrapped;
}
private void createQuery(StringBuilder declaration) {
declaration
.append("\treturn ")
.append(sessionName)
.append(".createQuery(query)");
final boolean hasOrderParameter =
paramTypes.stream().anyMatch(AbstractQueryMethod::isOrderParam);
final boolean hasEnabledFetchProfiles = !fetchProfiles.isEmpty();
final boolean hasNativeReturnType =
}
private void execute(StringBuilder declaration, List<String> paramTypes, boolean unwrapped) {
final boolean mustUnwrap =
containerType != null && containerType.startsWith("org.hibernate");
final boolean unwrap =
( hasOrderParameter || hasEnabledFetchProfiles || hasNativeReturnType )
&& isUsingEntityManager();
if ( unwrap ) {
declaration
.append("\n\t\t\t.unwrap(")
.append(annotationMetaEntity.importType(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, paramType );
}
else if ( isOrderParam(paramType) && !isJakartaSortParam(paramType) ) {
setOrder( declaration, true, paramName, paramType );
}
}
enableFetchProfile(declaration);
if ( containerType == null) {
if ( unwrap || hasEnabledFetchProfiles ) {
declaration.append("\n\t\t\t");
}
declaration
.append(".getSingleResult()");
}
else if ( containerType.equals(OPTIONAL) ) {
unwrapQuery( declaration, unwrap );
declaration
.append("\n\t\t\t.uniqueResultOptional()");
}
else if ( containerType.equals(STREAM) ) {
if ( unwrap || hasOrderParameter || hasEnabledFetchProfiles ) {
declaration.append("\n\t\t\t");
}
declaration
.append(".getResultStream()");
}
else if ( containerType.equals(LIST) ) {
if ( unwrap || hasOrderParameter || hasEnabledFetchProfiles ) {
declaration.append("\n\t\t\t");
}
declaration
.append(".getResultList()");
}
else if ( containerType.equals(HIB_KEYED_RESULT_LIST) ) {
if ( unwrap || hasOrderParameter || hasEnabledFetchProfiles ) {
declaration.append("\n\t\t\t");
}
for (int i = 0; i < paramTypes.size(); i++) {
if ( isKeyedPageParam( paramTypes.get(i) ) ) {
declaration
.append(".getKeyedResultList(")
.append(paramNames.get(i))
.append(')');
}
}
}
declaration
.append(';');
if (dataRepository) {
executeSelect( declaration, paramTypes, containerType, unwrapped, mustUnwrap );
if ( dataRepository ) {
declaration
.append('\n');
}
}
private void createQuery(StringBuilder declaration) {
private boolean handleSpecialParameters(StringBuilder declaration, List<String> paramTypes, boolean unwrapped) {
if ( containerType == null || !containerType.equals(JD_KEYED_SLICE) ) {
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, paramType );
}
else if ( isOrderParam(paramType) && !isJakartaSortParam(paramType) ) {
setOrder( declaration, unwrapped, paramName, paramType );
unwrapped = true;
}
}
}
return unwrapped;
}
private void tryReturn(StringBuilder declaration, List<String> paramTypes) {
if (dataRepository) {
declaration
.append("\ttry {\n");
}
if ( containerType != null
&& containerType.equals(JD_KEYED_SLICE) ) {
makeKeyedPage(declaration, paramTypes);
}
else {
if ( dataRepository ) {
declaration
.append('\t');
}
declaration
.append("\treturn ");
}
}
private void createCriteriaQuery(StringBuilder declaration) {
declaration
.append("\n\tvar builder = ")
.append(sessionName)

View File

@ -80,7 +80,7 @@ public class IdFinderMethod extends AbstractFinderMethod {
.append(".byId(")
.append(annotationMetaEntity.importType(entity))
.append(".class)");
enableFetchProfile(declaration);
enableFetchProfile( declaration, true );
declaration
.append("\n\t\t\t.load(")
.append(paramName)

View File

@ -65,7 +65,7 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
.append(".byNaturalId(")
.append(annotationMetaEntity.importType(entity))
.append(".class)");
enableFetchProfile( declaration );
enableFetchProfile( declaration, true );
for ( int i = 0; i < paramNames.size(); i ++ ) {
if ( !isSessionParameter( paramTypes.get(i) ) ) {
final String paramName = paramNames.get(i);

View File

@ -13,11 +13,14 @@ import org.hibernate.jpamodelgen.util.Constants;
import java.util.Arrays;
import java.util.List;
import static org.hibernate.jpamodelgen.util.Constants.HIB_KEYED_RESULT_LIST;
import static org.hibernate.jpamodelgen.util.Constants.HIB_ORDER;
import static org.hibernate.jpamodelgen.util.Constants.HIB_QUERY;
import static org.hibernate.jpamodelgen.util.Constants.HIB_SELECTION_QUERY;
import static org.hibernate.jpamodelgen.util.Constants.JD_KEYED_SLICE;
import static org.hibernate.jpamodelgen.util.Constants.LIST;
import static org.hibernate.jpamodelgen.util.Constants.OPTIONAL;
import static org.hibernate.jpamodelgen.util.Constants.STREAM;
import static org.hibernate.jpamodelgen.util.Constants.QUERY;
import static org.hibernate.jpamodelgen.util.Constants.TYPED_QUERY;
import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase;
/**
@ -26,7 +29,7 @@ import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFr
*/
public class QueryMethod extends AbstractQueryMethod {
private final String queryString;
private final @Nullable String containerTypeName;
private final @Nullable String containerType;
private final boolean isUpdate;
private final boolean isNative;
private final List<OrderBy> orderBys;
@ -38,7 +41,7 @@ public class QueryMethod extends AbstractQueryMethod {
@Nullable
String returnTypeName,
@Nullable
String containerTypeName,
String containerType,
List<String> paramNames,
List<String> paramTypes,
boolean isUpdate,
@ -56,7 +59,7 @@ public class QueryMethod extends AbstractQueryMethod {
belongsToDao, addNonnullAnnotation,
dataRepository );
this.queryString = queryString;
this.containerTypeName = containerTypeName;
this.containerType = containerType;
this.isUpdate = isUpdate;
this.isNative = isNative;
this.orderBys = orderBys;
@ -79,7 +82,7 @@ public class QueryMethod extends AbstractQueryMethod {
@Override
boolean singleResult() {
return containerTypeName == null;
return containerType == null;
}
@Override
@ -93,14 +96,46 @@ public class QueryMethod extends AbstractQueryMethod {
tryReturn( declaration );
castResult( declaration, returnType );
createQuery( declaration );
boolean unwrapped = setParameters( paramTypes, declaration );
unwrapped = orderBy( declaration, unwrapped);
setParameters( paramTypes, declaration );
boolean unwrapped = specialNeeds( paramTypes, declaration );
execute( declaration, unwrapped );
convertExceptions( declaration );
closingBrace( declaration );
return declaration.toString();
}
private boolean specialNeeds(List<String> paramTypes, StringBuilder declaration) {
boolean unwrapped;
if ( containerType == null || !containerType.equals(JD_KEYED_SLICE) ) {
unwrapped = handleSpecialParameters( paramTypes, declaration );
unwrapped = orderBy( declaration, unwrapped );
}
else {
unwrapped = !isUsingEntityManager();
}
unwrapped = unwrapIfOptional( declaration, unwrapped );
if ( isUpdate || containerType == null || !isQueryType(containerType)) {
declaration
.append("\n\t\t\t");
}
return unwrapped;
}
private boolean unwrapIfOptional(StringBuilder declaration, boolean unwrapped) {
if ( OPTIONAL.equals(containerType) ) {
unwrapQuery(declaration, unwrapped);
unwrapped = true;
}
return unwrapped;
}
private boolean isQueryType(String containerType) {
return HIB_QUERY.equals(containerType)
|| HIB_SELECTION_QUERY.equals(containerType)
|| QUERY.equals(containerType)
|| TYPED_QUERY.equals(containerType);
}
private boolean orderBy(StringBuilder declaration, boolean unwrapped) {
if ( !orderBys.isEmpty() && returnTypeName!=null ) {
unwrapQuery( declaration, unwrapped );
@ -155,7 +190,7 @@ public class QueryMethod extends AbstractQueryMethod {
}
private void castResult(StringBuilder declaration, StringBuilder returnType) {
if ( isNative && returnTypeName != null && containerTypeName == null
if ( isNative && returnTypeName != null && containerType == null
&& isUsingEntityManager() ) {
// EntityManager.createNativeQuery() does not return TypedQuery,
// so we need to cast to the entity type
@ -168,13 +203,23 @@ public class QueryMethod extends AbstractQueryMethod {
private void tryReturn(StringBuilder declaration) {
if (dataRepository) {
declaration
.append("\ttry {\n\t");
.append("\ttry {\n");
}
declaration
.append("\t");
if ( returnTypeName == null || !returnTypeName.equals("void") ) {
if ( containerType != null
&& containerType.equals(JD_KEYED_SLICE) ) {
makeKeyedPage( declaration, paramTypes );
}
else {
if ( dataRepository ) {
declaration
.append('\t');
}
declaration
.append("return ");
.append("\t");
if ( returnTypeName == null || !returnTypeName.equals("void") ) {
declaration
.append("return ");
}
}
}
@ -191,61 +236,30 @@ public class QueryMethod extends AbstractQueryMethod {
private void execute(StringBuilder declaration, boolean unwrapped) {
if ( isUpdate ) {
declaration
.append("\n\t\t\t.executeUpdate()");
.append(".executeUpdate()");
if ( "boolean".equals(returnTypeName) ) {
declaration.append(" > 0");
}
}
else if ( containerTypeName == null ) {
declaration
.append("\n\t\t\t.getSingleResult()");
}
else if ( containerTypeName.equals(OPTIONAL) ) {
unwrapQuery( declaration, unwrapped );
declaration
.append("\n\t\t\t.uniqueResultOptional()");
}
else if ( containerTypeName.equals(STREAM) ) {
declaration
.append("\n\t\t\t.getResultStream()");
}
else if ( containerTypeName.equals(LIST) ) {
declaration
.append("\n\t\t\t.getResultList()");
}
else if ( containerTypeName.equals(HIB_KEYED_RESULT_LIST) ) {
for (int i = 0; i < paramTypes.size(); i++) {
if ( isKeyedPageParam( paramTypes.get(i) ) ) {
declaration
.append("\n\t\t\t.getKeyedResultList(")
.append(paramNames.get(i))
.append(')');
}
}
.append(';');
}
else {
if ( isUsingEntityManager() && !unwrapped
&& ( containerTypeName.startsWith("org.hibernate")
|| isNative && returnTypeName != null ) ) {
declaration
.append("\n\t\t\t.unwrap(")
.append(annotationMetaEntity.importType(containerTypeName))
.append(".class)");
}
final boolean mustUnwrap =
containerType != null && containerType.startsWith("org.hibernate")
|| isNative && returnTypeName != null;
executeSelect( declaration, paramTypes, containerType, unwrapped, mustUnwrap );
}
declaration.append(';');
if (dataRepository) {
declaration.append('\n');
if ( dataRepository ) {
declaration
.append('\n');
}
}
private boolean setParameters(List<String> paramTypes, StringBuilder declaration) {
boolean unwrapped = !isUsingEntityManager();
private void setParameters(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 ( !isSessionParameter(paramType) ) {
if ( !isSpecialParam(paramType) ) {
final int ordinal = i+1;
if ( queryString.contains(":" + paramName) ) {
setNamedParameter( declaration, paramName );
@ -253,12 +267,20 @@ public class QueryMethod extends AbstractQueryMethod {
else if ( queryString.contains("?" + ordinal) ) {
setOrdinalParameter( declaration, ordinal, paramName );
}
else if ( isPageParam(paramType) ) {
setPage( declaration, paramName, paramType );
}
else if ( isOrderParam(paramType) ) {
unwrapped = setOrder( declaration, unwrapped, paramName, paramType );
}
}
}
}
private boolean handleSpecialParameters(List<String> paramTypes, StringBuilder declaration) {
boolean unwrapped = !isUsingEntityManager();
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, paramType );
}
else if ( isOrderParam(paramType) ) {
unwrapped = setOrder( declaration, unwrapped, paramName, paramType );
}
}
return unwrapped;
@ -285,12 +307,12 @@ public class QueryMethod extends AbstractQueryMethod {
private StringBuilder returnType() {
StringBuilder type = new StringBuilder();
boolean returnsUni = isReactive()
&& (containerTypeName == null || LIST.equals(containerTypeName));
&& (containerType == null || LIST.equals(containerType));
if ( returnsUni ) {
type.append(annotationMetaEntity.importType(Constants.UNI)).append('<');
}
if ( containerTypeName != null ) {
type.append(annotationMetaEntity.importType(containerTypeName));
if ( containerType != null ) {
type.append(annotationMetaEntity.importType(containerType));
if ( returnTypeName != null ) {
type.append("<").append(annotationMetaEntity.importType(returnTypeName)).append(">");
}

View File

@ -72,6 +72,7 @@ public final class Constants {
public static final String JD_PAGE_REQUEST = "jakarta.data.page.PageRequest";
public static final String JD_SORT = "jakarta.data.Sort";
public static final String JD_ORDER = "jakarta.data.Order";
public static final String JD_KEYED_SLICE = "jakarta.data.page.KeysetAwareSlice";
public static final String HIB_ORDER = "org.hibernate.query.Order";
public static final String HIB_PAGE = "org.hibernate.query.Page";
@ -101,14 +102,14 @@ public final class Constants {
public static final String LIST_ATTRIBUTE = "jakarta.persistence.metamodel.ListAttribute";
public static final String MAP_ATTRIBUTE = "jakarta.persistence.metamodel.MapAttribute";
public static final String JAVA_OBJECT = Object.class.getName();
public static final String ITERABLE = java.lang.Iterable.class.getName();
public static final String COLLECTION = java.util.Collection.class.getName();
public static final String LIST = java.util.List.class.getName();
public static final String MAP = java.util.Map.class.getName();
public static final String SET = java.util.Set.class.getName();
public static final String OPTIONAL = java.util.Optional.class.getName();
public static final String STREAM = java.util.stream.Stream.class.getName();
public static final String JAVA_OBJECT = "java.lang.Object";
public static final String ITERABLE = "java.lang.Iterable";
public static final String COLLECTION = "java.util.Collection";
public static final String LIST = "java.util.List";
public static final String MAP = "java.util.Map";
public static final String SET = "java.util.Set";
public static final String OPTIONAL = "java.util.Optional";
public static final String STREAM = "java.util.stream.Stream";
public static final Map<String, String> COLLECTIONS = Map.of(
COLLECTION, Constants.COLLECTION_ATTRIBUTE,

View File

@ -19,7 +19,7 @@ import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassG
public class DaoTest extends CompilationTest {
@Test
@WithClasses({ Book.class, Dao.class, Bean.class, StatefulDao.class, StatelessDao.class })
public void testGeneratedAnnotationNotGenerated() {
public void testDao() {
System.out.println( TestUtil.getMetaModelSourceAsString( Dao.class ) );
System.out.println( TestUtil.getMetaModelSourceAsString( StatefulDao.class ) );
System.out.println( TestUtil.getMetaModelSourceAsString( StatelessDao.class ) );

View File

@ -106,4 +106,16 @@ public interface BookAuthorRepository {
@OrderBy("isbn")
@OrderBy(value = "publicationDate", descending = true)
List<Book> everyBook3(PageRequest<? super Book> pageRequest);
@Find
KeysetAwareSlice<Book> everyBook4(PageRequest<Book> pageRequest);
@Find
KeysetAwareSlice<Book> everyBook5(String title, PageRequest<Book> pageRequest);
@Query("from Book")
KeysetAwareSlice<Book> everyBook6(PageRequest<Book> pageRequest);
@Query("from Book where title like :titlePattern")
KeysetAwareSlice<Book> everyBook7(String titlePattern, PageRequest<Book> pageRequest);
}