better handling of instantiation for @HQL methods
This commit is contained in:
parent
d2ca21603b
commit
97099c0280
|
@ -318,6 +318,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
|
||||
private final Class<R> expectedResultType;
|
||||
private final String expectedResultTypeName;
|
||||
private final String expectedResultTypeShortName;
|
||||
private final String expectedResultEntity;
|
||||
private final SqmCreationOptions creationOptions;
|
||||
private final SqmCreationContext creationContext;
|
||||
|
@ -347,24 +349,53 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
this( expectedResultType, null, creationOptions, creationContext, query );
|
||||
this( expectedResultType,
|
||||
expectedResultType == null ? null : expectedResultType.getTypeName(),
|
||||
expectedResultType == null ? null : expectedResultType.getSimpleName(),
|
||||
null, creationOptions, creationContext, query );
|
||||
}
|
||||
|
||||
public SemanticQueryBuilder(
|
||||
String expectedResultTypeName,
|
||||
String expectedResultTypeShortName,
|
||||
String expectedResultEntity,
|
||||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
this( null, expectedResultEntity, creationOptions, creationContext, query );
|
||||
this( null,
|
||||
expectedResultTypeName,
|
||||
expectedResultTypeShortName,
|
||||
expectedResultEntity,
|
||||
creationOptions, creationContext,
|
||||
query );
|
||||
}
|
||||
|
||||
public SemanticQueryBuilder(
|
||||
String expectedResultTypeName,
|
||||
String expectedResultTypeShortName,
|
||||
Class<R> expectedResultType,
|
||||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
this( expectedResultType,
|
||||
expectedResultTypeName,
|
||||
expectedResultTypeShortName,
|
||||
null,
|
||||
creationOptions, creationContext,
|
||||
query );
|
||||
}
|
||||
|
||||
private SemanticQueryBuilder(
|
||||
Class<R> expectedResultType,
|
||||
String expectedResultTypeName,
|
||||
String expectedResultTypeShortName,
|
||||
String expectedResultEntity,
|
||||
SqmCreationOptions creationOptions,
|
||||
SqmCreationContext creationContext,
|
||||
String query) {
|
||||
this.expectedResultType = expectedResultType;
|
||||
this.expectedResultTypeName = expectedResultTypeName;
|
||||
this.expectedResultTypeShortName = expectedResultTypeShortName;
|
||||
this.expectedResultEntity = expectedResultEntity;
|
||||
this.creationOptions = creationOptions;
|
||||
this.creationContext = creationContext;
|
||||
|
@ -1272,7 +1303,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final EntityDomainType<R> entityDescriptor = jpaMetamodel.findEntityType( expectedResultType );
|
||||
if ( entityDescriptor == null ) {
|
||||
throw new SemanticException( "Query has no 'from' clause, and the result type '"
|
||||
+ expectedResultType.getSimpleName() + "' is not an entity type", query );
|
||||
+ expectedResultTypeShortName + "' is not an entity type", query );
|
||||
}
|
||||
return entityDescriptor;
|
||||
}
|
||||
|
@ -1427,8 +1458,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
final ParseTree instantiationTarget = ctx.instantiationTarget().getChild( 0 );
|
||||
if ( instantiationTarget instanceof HqlParser.SimplePathContext ) {
|
||||
String className = instantiationTarget.getText();
|
||||
if ( expectedResultType!=null && expectedResultType.getSimpleName().equals( className ) ) {
|
||||
className = expectedResultType.getName();
|
||||
if ( expectedResultTypeName != null && expectedResultTypeShortName.equals( className ) ) {
|
||||
className = expectedResultTypeName;
|
||||
}
|
||||
try {
|
||||
dynamicInstantiation = SqmDynamicInstantiation.forClassInstantiation(
|
||||
|
|
|
@ -27,6 +27,7 @@ import javax.lang.model.type.ExecutableType;
|
|||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.type.WildcardType;
|
||||
import javax.lang.model.util.Types;
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
@ -1028,6 +1029,15 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
final List<String> paramNames = parameterNames( method );
|
||||
final List<String> paramTypes = parameterTypes( method );
|
||||
final String[] sessionType = sessionTypeFromParameters( paramNames, paramTypes );
|
||||
if ( returnType != null && returnType.getKind() == TypeKind.DECLARED ) {
|
||||
if ( !((DeclaredType) returnType).getTypeArguments().isEmpty() ) {
|
||||
context.message( method, mirror, value,
|
||||
"query result type may not be a generic type"
|
||||
+ " (change '" + returnType +
|
||||
"' to '" + context.getTypeUtils().erasure( returnType ) + "')",
|
||||
Diagnostic.Kind.ERROR );
|
||||
}
|
||||
}
|
||||
final QueryMethod attribute =
|
||||
new QueryMethod(
|
||||
this,
|
||||
|
@ -1150,7 +1160,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
try {
|
||||
final Class<?> javaResultType = selection.getJavaType();
|
||||
final TypeElement typeElement = context.getTypeElementForFullyQualifiedName( javaResultType.getName() );
|
||||
returnTypeCorrect = context.getTypeUtils().isAssignable( returnType, typeElement.asType() );
|
||||
final Types types = context.getTypeUtils();
|
||||
returnTypeCorrect = types.isAssignable( returnType, types.erasure( typeElement.asType() ) );
|
||||
}
|
||||
catch (Exception e) {
|
||||
//ignore
|
||||
|
|
|
@ -104,11 +104,15 @@ public class Validation {
|
|||
if ( returnType != null && returnType.getKind() == TypeKind.DECLARED ) {
|
||||
final DeclaredType declaredType = (DeclaredType) returnType;
|
||||
final TypeElement typeElement = (TypeElement) declaredType.asElement();
|
||||
if ( isEntity( typeElement ) ) {
|
||||
return new SemanticQueryBuilder<>( getEntityName( typeElement ), () -> false, factory, hql );
|
||||
}
|
||||
final String typeName = typeElement.getQualifiedName().toString();
|
||||
final String shortName = typeElement.getSimpleName().toString();
|
||||
return isEntity( typeElement )
|
||||
? new SemanticQueryBuilder<>( typeName, shortName, getEntityName(typeElement), () -> false, factory, hql )
|
||||
: new SemanticQueryBuilder<>( typeName, shortName, Object[].class, () -> false, factory, hql );
|
||||
}
|
||||
else {
|
||||
return new SemanticQueryBuilder<>( Object[].class, () -> false, factory, hql );
|
||||
}
|
||||
return new SemanticQueryBuilder<>( Object[].class, () -> false, factory, hql );
|
||||
}
|
||||
|
||||
private static HqlParser.StatementContext parseAndCheckSyntax(String hql, Handler handler) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.hibernate.query.Page;
|
|||
import org.hibernate.query.SelectionQuery;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface Dao {
|
||||
|
||||
|
@ -48,10 +49,19 @@ public interface Dao {
|
|||
@HQL("from Book book join fetch book.publisher where book.title like :titlePattern")
|
||||
List<Book> booksWithPublisherByTitle(String titlePattern, Page page, Order<? super Book> order);
|
||||
|
||||
@HQL("select new org.hibernate.jpamodelgen.test.hqlsql.Dto(title, pages) from Book")
|
||||
@HQL("select title, pages from Book")
|
||||
List<Dto> dtoQuery();
|
||||
|
||||
@HQL("select title, pages from Book")
|
||||
@HQL("select new org.hibernate.jpamodelgen.test.hqlsql.Dto(title, pages) from Book")
|
||||
List<Dto> dtoQuery1();
|
||||
|
||||
@HQL("select new Dto(title, pages) from Book")
|
||||
List<Dto> dtoQuery2();
|
||||
|
||||
@HQL("select new map(title as title, pages as pages) from Book")
|
||||
List<Map> dtoQuery3();
|
||||
|
||||
@HQL("select new list(title, pages) from Book")
|
||||
List<List> dtoQuery4();
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue