allow @Query methods to return array
This commit is contained in:
parent
813ae8ed9d
commit
4bb5bc60e9
|
@ -107,8 +107,14 @@ public interface BookAuthorRepository {
|
|||
@Query("from Book where title like :title")
|
||||
List<Book> books3(String title, Limit limit, Sort<Book>... order);
|
||||
|
||||
@Query("from Book where title like :title")
|
||||
Book[] books4(String title, Sort<Book> sort);
|
||||
|
||||
@Query("select title from Book where title like :title order by isbn")
|
||||
Stream<String> titles(String title);
|
||||
Stream<String> titles0(String title);
|
||||
|
||||
@Query("select title from Book where title like :title order by isbn")
|
||||
String[] titles1(String title);
|
||||
|
||||
@Query("from Book")
|
||||
List<Book> everyBook1(PageRequest<? super Book> pageRequest);
|
||||
|
|
|
@ -139,7 +139,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
/**
|
||||
* The type of the "session getter" method of a DAO-style repository.
|
||||
*/
|
||||
private String sessionType = Constants.ENTITY_MANAGER;
|
||||
private String sessionType = ENTITY_MANAGER;
|
||||
|
||||
/**
|
||||
* The field or method call to obtain the session
|
||||
|
@ -456,34 +456,41 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
|
||||
private boolean isPanacheType(TypeElement type) {
|
||||
return isOrmPanacheType( type ) || isReactivePanacheType( type );
|
||||
return isOrmPanacheType( type )
|
||||
|| isReactivePanacheType( type );
|
||||
}
|
||||
|
||||
private boolean isOrmPanacheType(TypeElement type) {
|
||||
ProcessingEnvironment processingEnvironment = this.context.getProcessingEnvironment();
|
||||
TypeElement panacheRepositorySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_ORM_REPOSITORY_BASE );
|
||||
TypeElement panacheEntitySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_ORM_ENTITY_BASE );
|
||||
final ProcessingEnvironment processingEnvironment = context.getProcessingEnvironment();
|
||||
final Elements elements = processingEnvironment.getElementUtils();
|
||||
final TypeElement panacheRepositorySuperType = elements.getTypeElement( PANACHE_ORM_REPOSITORY_BASE );
|
||||
final TypeElement panacheEntitySuperType = elements.getTypeElement( PANACHE_ORM_ENTITY_BASE );
|
||||
if ( panacheRepositorySuperType == null || panacheEntitySuperType == null ) {
|
||||
return false;
|
||||
}
|
||||
Types types = processingEnvironment.getTypeUtils();
|
||||
// check against a raw supertype of PanacheRepositoryBase, which .asType() is not
|
||||
return processingEnvironment.getTypeUtils().isSubtype( type.asType(), types.getDeclaredType( panacheRepositorySuperType ) )
|
||||
|| processingEnvironment.getTypeUtils().isSubtype( type.asType(), panacheEntitySuperType.asType() );
|
||||
else {
|
||||
final Types types = processingEnvironment.getTypeUtils();
|
||||
// check against a raw supertype of PanacheRepositoryBase, which .asType() is not
|
||||
return types.isSubtype( type.asType(), types.getDeclaredType( panacheRepositorySuperType ) )
|
||||
|| types.isSubtype( type.asType(), panacheEntitySuperType.asType() );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isReactivePanacheType(TypeElement type) {
|
||||
ProcessingEnvironment processingEnvironment = this.context.getProcessingEnvironment();
|
||||
TypeElement panacheRepositorySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_REACTIVE_REPOSITORY_BASE );
|
||||
TypeElement panacheEntitySuperType = processingEnvironment.getElementUtils().getTypeElement( Constants.PANACHE_REACTIVE_ENTITY_BASE );
|
||||
final ProcessingEnvironment processingEnvironment = context.getProcessingEnvironment();
|
||||
final Elements elements = processingEnvironment.getElementUtils();
|
||||
final TypeElement panacheRepositorySuperType = elements.getTypeElement( PANACHE_REACTIVE_REPOSITORY_BASE );
|
||||
final TypeElement panacheEntitySuperType = elements.getTypeElement( PANACHE_REACTIVE_ENTITY_BASE );
|
||||
|
||||
if ( panacheRepositorySuperType == null || panacheEntitySuperType == null ) {
|
||||
return false;
|
||||
}
|
||||
Types types = processingEnvironment.getTypeUtils();
|
||||
// check against a raw supertype of PanacheRepositoryBase, which .asType() is not
|
||||
return types.isSubtype( type.asType(), types.getDeclaredType( panacheRepositorySuperType ) )
|
||||
|| types.isSubtype( type.asType(), panacheEntitySuperType.asType());
|
||||
else {
|
||||
final Types types = processingEnvironment.getTypeUtils();
|
||||
// check against a raw supertype of PanacheRepositoryBase, which .asType() is not
|
||||
return types.isSubtype( type.asType(), types.getDeclaredType( panacheRepositorySuperType ) )
|
||||
|| types.isSubtype( type.asType(), panacheEntitySuperType.asType() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -546,7 +553,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
true
|
||||
)
|
||||
);
|
||||
return Constants.ENTITY_MANAGER;
|
||||
return ENTITY_MANAGER;
|
||||
}
|
||||
else {
|
||||
importType( Constants.QUARKUS_SESSION_OPERATIONS );
|
||||
|
@ -570,10 +577,10 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
if ( element.getKind() == ElementKind.INTERFACE ) {
|
||||
final TypeElement typeElement = (TypeElement) element;
|
||||
final Name name = typeElement.getQualifiedName();
|
||||
return name.contentEquals(Constants.HIB_SESSION)
|
||||
|| name.contentEquals(Constants.HIB_STATELESS_SESSION)
|
||||
|| name.contentEquals(Constants.MUTINY_SESSION)
|
||||
|| name.contentEquals(Constants.ENTITY_MANAGER);
|
||||
return name.contentEquals(HIB_SESSION)
|
||||
|| name.contentEquals(HIB_STATELESS_SESSION)
|
||||
|| name.contentEquals(MUTINY_SESSION)
|
||||
|| name.contentEquals(ENTITY_MANAGER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -655,7 +662,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
private boolean isPersistent(Element memberOfClass, AccessType membersKind) {
|
||||
return ( entityAccessTypeInfo.getAccessType() == membersKind
|
||||
|| determineAnnotationSpecifiedAccessType( memberOfClass ) != null )
|
||||
&& !containsAnnotation( memberOfClass, Constants.TRANSIENT )
|
||||
&& !containsAnnotation( memberOfClass, TRANSIENT )
|
||||
&& !memberOfClass.getModifiers().contains( Modifier.TRANSIENT )
|
||||
&& !memberOfClass.getModifiers().contains( Modifier.STATIC )
|
||||
&& !( memberOfClass.getKind() == ElementKind.METHOD
|
||||
|
@ -1591,25 +1598,63 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
@Nullable TypeElement containerType,
|
||||
AnnotationMirror mirror,
|
||||
boolean isNative) {
|
||||
|
||||
final AnnotationValue value = getAnnotationValueRef( mirror, "value" );
|
||||
if ( value != null ) {
|
||||
final Object query = value.getValue();
|
||||
if ( query instanceof String ) {
|
||||
final String queryString = (String) query;
|
||||
|
||||
// The following is quite fragile!
|
||||
final String containerTypeName;
|
||||
if ( containerType == null ) {
|
||||
if ( returnType != null && returnType.getKind() == TypeKind.ARRAY ) {
|
||||
final ArrayType arrayType = (ArrayType) returnType;
|
||||
final TypeMirror componentType = arrayType.getComponentType();
|
||||
final TypeElement object = context.getElementUtils().getTypeElement(JAVA_OBJECT);
|
||||
if ( !context.getTypeUtils().isSameType( object.asType(), componentType ) ) {
|
||||
returnType = componentType;
|
||||
containerTypeName = "[]";
|
||||
}
|
||||
else {
|
||||
// assume it's returning a single tuple as Object[]
|
||||
containerTypeName = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
containerTypeName = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
containerTypeName = containerType.getQualifiedName().toString();
|
||||
}
|
||||
|
||||
final List<String> paramNames = parameterNames( method );
|
||||
final List<String> paramTypes = parameterTypes( method );
|
||||
|
||||
if ( isNative ) {
|
||||
validateSql( method, mirror, queryString, paramNames, value );
|
||||
}
|
||||
else {
|
||||
validateHql( method, returnType, mirror, value, queryString, paramNames, paramTypes );
|
||||
}
|
||||
|
||||
// now check that the query has a parameter for every method parameter
|
||||
checkParameters( method, returnType, paramNames, paramTypes, mirror, value, queryString );
|
||||
|
||||
final String[] sessionType = sessionTypeFromParameters( paramNames, paramTypes );
|
||||
final DeclaredType resultType = resultType( method, returnType, mirror, value );
|
||||
final List<OrderBy> orderBys = resultType == null
|
||||
? emptyList()
|
||||
: orderByList( method, (TypeElement) resultType.asElement() );
|
||||
|
||||
final QueryMethod attribute =
|
||||
new QueryMethod(
|
||||
this,
|
||||
method.getSimpleName().toString(),
|
||||
queryString,
|
||||
returnType == null ? null : returnType.toString(),
|
||||
containerType == null ? null : containerType.getQualifiedName().toString(),
|
||||
containerTypeName,
|
||||
paramNames,
|
||||
paramTypes,
|
||||
isInsertUpdateDelete( queryString ),
|
||||
|
@ -1622,16 +1667,6 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
jakartaDataRepository
|
||||
);
|
||||
putMember( attribute.getPropertyName() + paramTypes, attribute );
|
||||
|
||||
if ( isNative ) {
|
||||
validateSql( method, mirror, queryString, paramNames, value );
|
||||
}
|
||||
else {
|
||||
validateHql( method, returnType, mirror, value, queryString, paramNames, paramTypes );
|
||||
}
|
||||
|
||||
// now check that the query has a parameter for every method parameter
|
||||
checkParameters( method, returnType, paramNames, paramTypes, mirror, value, queryString );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1710,9 +1745,9 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
if ( reactive ) {
|
||||
// for reactive calls, don't use the returnType param, which has been ununi-ed, we want to check the full one
|
||||
final String returnTypeName = method.getReturnType().toString();
|
||||
return returnTypeName.equals( Constants.UNI_VOID )
|
||||
|| returnTypeName.equals( Constants.UNI_BOOLEAN )
|
||||
|| returnTypeName.equals( Constants.UNI_INTEGER );
|
||||
return returnTypeName.equals( UNI_VOID )
|
||||
|| returnTypeName.equals( UNI_BOOLEAN )
|
||||
|| returnTypeName.equals( UNI_INTEGER );
|
||||
|
||||
}
|
||||
else {
|
||||
|
@ -1833,9 +1868,9 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
final TypeElement typeElement = (TypeElement) returnType.asElement();
|
||||
final Name qualifiedName = typeElement.getQualifiedName();
|
||||
if ( qualifiedName.contentEquals(Constants.TUPLE)
|
||||
|| qualifiedName.contentEquals(Constants.LIST)
|
||||
|| qualifiedName.contentEquals(Constants.MAP) ) {
|
||||
if ( qualifiedName.contentEquals(TUPLE)
|
||||
|| qualifiedName.contentEquals(LIST)
|
||||
|| qualifiedName.contentEquals(MAP) ) {
|
||||
// these are exceptionally allowed
|
||||
return true;
|
||||
}
|
||||
|
@ -1903,7 +1938,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
if ( componentType.getKind() == TypeKind.DECLARED ) {
|
||||
final DeclaredType declaredType = (DeclaredType) componentType;
|
||||
final TypeElement typeElement = (TypeElement) declaredType.asElement();
|
||||
return typeElement.getQualifiedName().contentEquals(Constants.JAVA_OBJECT);
|
||||
return typeElement.getQualifiedName().contentEquals(JAVA_OBJECT);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
@ -2114,11 +2149,11 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
}
|
||||
|
||||
private boolean usingReactiveSession(String sessionType) {
|
||||
return Constants.MUTINY_SESSION.equals(sessionType)
|
||||
return MUTINY_SESSION.equals(sessionType)
|
||||
|| Constants.UNI_MUTINY_SESSION.equals(sessionType);
|
||||
}
|
||||
|
||||
private boolean usingStatelessSession(String sessionType) {
|
||||
return Constants.HIB_STATELESS_SESSION.equals(sessionType);
|
||||
return HIB_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.processor.annotation;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.processor.util.Constants;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -199,8 +200,9 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
|||
.append(".in(");
|
||||
if ( paramType.endsWith("[]") ) {
|
||||
declaration
|
||||
//TODO: only safe if we are binding literals as parameters!!!
|
||||
.append(parameterName);
|
||||
.append("(Object[]) ")
|
||||
//TODO: only safe if we are binding literals as parameters!!!
|
||||
.append(parameterName);
|
||||
|
||||
}
|
||||
else {
|
||||
|
@ -247,7 +249,10 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
|||
private StringBuilder returnType() {
|
||||
final StringBuilder type = new StringBuilder();
|
||||
if ( "[]".equals(containerType) ) {
|
||||
type.append(returnTypeName).append("[]");
|
||||
if ( returnTypeName == null ) {
|
||||
throw new AssertionFailure("array return type, but no type name");
|
||||
}
|
||||
type.append(annotationMetaEntity.importType(returnTypeName)).append("[]");
|
||||
}
|
||||
else {
|
||||
boolean returnsUni = isReactive()
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.processor.annotation;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.processor.util.Constants;
|
||||
|
||||
|
@ -192,23 +193,31 @@ public class QueryMethod extends AbstractQueryMethod {
|
|||
}
|
||||
|
||||
private StringBuilder returnType() {
|
||||
StringBuilder type = new StringBuilder();
|
||||
boolean returnsUni = isReactive()
|
||||
&& (containerType == null || LIST.equals(containerType));
|
||||
if ( returnsUni ) {
|
||||
type.append(annotationMetaEntity.importType(Constants.UNI)).append('<');
|
||||
}
|
||||
if ( containerType != null ) {
|
||||
type.append(annotationMetaEntity.importType(containerType));
|
||||
if ( returnTypeName != null ) {
|
||||
type.append("<").append(annotationMetaEntity.importType(returnTypeName)).append(">");
|
||||
final StringBuilder type = new StringBuilder();
|
||||
if ( "[]".equals(containerType) ) {
|
||||
if ( returnTypeName == null ) {
|
||||
throw new AssertionFailure("array return type, but no type name");
|
||||
}
|
||||
type.append(annotationMetaEntity.importType(returnTypeName)).append("[]");
|
||||
}
|
||||
else if ( returnTypeName != null ) {
|
||||
type.append(annotationMetaEntity.importType(returnTypeName));
|
||||
}
|
||||
if ( returnsUni ) {
|
||||
type.append('>');
|
||||
else {
|
||||
boolean returnsUni = isReactive()
|
||||
&& (containerType == null || LIST.equals(containerType));
|
||||
if ( returnsUni ) {
|
||||
type.append(annotationMetaEntity.importType(Constants.UNI)).append('<');
|
||||
}
|
||||
if ( containerType != null ) {
|
||||
type.append(annotationMetaEntity.importType(containerType));
|
||||
if ( returnTypeName != null ) {
|
||||
type.append("<").append(annotationMetaEntity.importType(returnTypeName)).append(">");
|
||||
}
|
||||
}
|
||||
else if ( returnTypeName != null ) {
|
||||
type.append(annotationMetaEntity.importType(returnTypeName));
|
||||
}
|
||||
if ( returnsUni ) {
|
||||
type.append('>');
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,9 @@ public interface Dao {
|
|||
@HQL("order by isbn asc, publicationDate desc")
|
||||
List<Book> allBooks();
|
||||
|
||||
@HQL("order by isbn asc, publicationDate desc")
|
||||
Book[] allBooksAsArray();
|
||||
|
||||
@SQL("select * from Book where isbn = :isbn")
|
||||
Book findByIsbnNative(String isbn);
|
||||
|
||||
|
|
Loading…
Reference in New Issue