clarify use of Order and Page with @Find

[It's allowed!]
This commit is contained in:
Gavin King 2024-02-02 15:08:59 +01:00
parent 39457c5e12
commit d96b5dfffc
3 changed files with 40 additions and 8 deletions

View File

@ -516,7 +516,7 @@ This lets us declare which associations of `Book` should be pre-fetched by annot
[[paging-and-ordering]] [[paging-and-ordering]]
=== Paging and ordering === Paging and ordering
Optionally, a query method may have additional "magic" parameters which do not map to query parameters: Optionally, a query method--or a finder method which returns multiple results--may have additional "magic" parameters which do not map to query parameters:
[cols="19,~,32m"] [cols="19,~,32m"]
|=== |===
@ -537,7 +537,8 @@ Thus, if we redefine our earlier query method as follows:
---- ----
interface Queries { interface Queries {
@HQL("from Book where title like :title and type = :type") @HQL("from Book where title like :title and type = :type")
List<Book> findBooksByTitleAndType(String title, Page page, Order<? super Book>... order); List<Book> findBooksByTitleAndType(String title, Type type,
Page page, Order<? super Book>... order);
} }
---- ----
@ -550,6 +551,19 @@ List<Book> books =
Page.page(RESULTS_PER_PAGE, page), Order.asc(Book_.isbn)); Page.page(RESULTS_PER_PAGE, page), Order.asc(Book_.isbn));
---- ----
Alternatively, we could have written this query method as a finder method:
[source,java]
----
interface Queries {
@Find
List<Book> getBooksByTitle(String title, Type type,
Page page, Order<? super Book>... order);
}
----
This gives some dynamic control over query execution, but what if would like direct control over the `Query` object?
Well, let's talk about the return type.
[[return-types]] [[return-types]]
=== Query and finder method return types === Query and finder method return types

View File

@ -91,7 +91,7 @@ import static java.lang.annotation.RetentionPolicy.CLASS;
* or one of the following types: * or one of the following types:
* <ul> * <ul>
* <li>{@link java.util.List java.util.List&lt;E&gt;}, * <li>{@link java.util.List java.util.List&lt;E&gt;},
* <li>{@code io.smallrye.mutiny.Uni&lt;E&gt;}, when used with Hibernate Reactive, * <li>{@code io.smallrye.mutiny.Uni<E>}, when used with Hibernate Reactive,
* <li>{@link org.hibernate.query.Query org.hibernate.query.Query&lt;E&gt;}, * <li>{@link org.hibernate.query.Query org.hibernate.query.Query&lt;E&gt;},
* <li>{@link org.hibernate.query.SelectionQuery org.hibernate.query.SelectionQuery&lt;E&gt;}, * <li>{@link org.hibernate.query.SelectionQuery org.hibernate.query.SelectionQuery&lt;E&gt;},
* <li>{@link jakarta.persistence.Query jakarta.persistence.Query&lt;E&gt;}, or * <li>{@link jakarta.persistence.Query jakarta.persistence.Query&lt;E&gt;}, or
@ -123,7 +123,16 @@ import static java.lang.annotation.RetentionPolicy.CLASS;
* <p> * <p>
* As an exception, the method may have at most one parameter of * As an exception, the method may have at most one parameter of
* type {@code EntityManager}, {@code Session}, * type {@code EntityManager}, {@code Session},
* {@code StatelessSession}, or {@code Mutiny.Session}. * {@code StatelessSession}, or {@code Mutiny.Session}. Furthermore,
* if the finder method returns multiple results, that is, if its
* return type is {@code List}, then it may also have:
* <ul>
* <li>a parameter with type {@code Page}, and/or
* <li>a parameter with type {@code Order<? super E>},
* {@code List<Order<? super E>>}, or {@code Order<? super E>...}
* (varargs) where {@code E} is the entity type returned by the
* query.
* </ul>
* *
* @see HQL * @see HQL
* @see SQL * @see SQL

View File

@ -545,6 +545,15 @@ public class AnnotationMetaEntity extends AnnotationMeta {
createCriteriaFinder( method, returnType, containerType, entity ); createCriteriaFinder( method, returnType, containerType, entity );
} }
else { else {
for ( VariableElement parameter : method.getParameters() ) {
final String type = parameter.asType().toString();
if ( isPageParam(type) ) {
context.message( parameter, "pagination would have no effect", Diagnostic.Kind.ERROR);
}
else if ( isOrderParam(type) ) {
context.message( parameter, "ordering would have no effect", Diagnostic.Kind.ERROR);
}
}
final long parameterCount = final long parameterCount =
method.getParameters().stream() method.getParameters().stream()
.filter(AnnotationMetaEntity::isFinderParameterMappingToAttribute) .filter(AnnotationMetaEntity::isFinderParameterMappingToAttribute)
@ -570,8 +579,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
private void createCriteriaFinder( private void createCriteriaFinder(
ExecutableElement method, TypeMirror returnType, @Nullable TypeElement containerType, TypeElement entity) { ExecutableElement method, TypeMirror returnType, @Nullable TypeElement containerType, TypeElement entity) {
final String methodName = method.getSimpleName().toString(); final String methodName = method.getSimpleName().toString();
final List<String> paramNames = parameterNames(method); final List<String> paramNames = parameterNames( method );
final List<String> paramTypes = parameterTypes(method); final List<String> paramTypes = parameterTypes( method );
final String[] sessionType = sessionTypeFromParameters( paramNames, paramTypes ); final String[] sessionType = sessionTypeFromParameters( paramNames, paramTypes );
final String methodKey = methodName + paramTypes; final String methodKey = methodName + paramTypes;
for ( VariableElement param : method.getParameters() ) { for ( VariableElement param : method.getParameters() ) {
@ -683,8 +692,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
method.getParameters().stream() method.getParameters().stream()
.filter(AnnotationMetaEntity::isFinderParameterMappingToAttribute) .filter(AnnotationMetaEntity::isFinderParameterMappingToAttribute)
.findFirst().orElseThrow(); .findFirst().orElseThrow();
final List<String> paramNames = parameterNames(method); final List<String> paramNames = parameterNames( method );
final List<String> paramTypes = parameterTypes(method); final List<String> paramTypes = parameterTypes( method );
final String[] sessionType = sessionTypeFromParameters( paramNames, paramTypes ); final String[] sessionType = sessionTypeFromParameters( paramNames, paramTypes );
final FieldType fieldType = validateFinderParameter( entity, parameter ); final FieldType fieldType = validateFinderParameter( entity, parameter );
if ( fieldType != null ) { if ( fieldType != null ) {