HHH-16633 support mutation query methods
This commit is contained in:
parent
4d005b3d19
commit
0918791f47
|
@ -417,7 +417,11 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
|
|
||||||
private void addQueryMethod(ExecutableElement method) {
|
private void addQueryMethod(ExecutableElement method) {
|
||||||
final TypeMirror returnType = method.getReturnType();
|
final TypeMirror returnType = method.getReturnType();
|
||||||
if ( returnType.getKind() == TypeKind.DECLARED ) {
|
final TypeKind kind = returnType.getKind();
|
||||||
|
if ( kind == TypeKind.VOID || kind.isPrimitive() ) {
|
||||||
|
addQueryMethod( method, returnType, null );
|
||||||
|
}
|
||||||
|
else if ( kind == TypeKind.DECLARED ) {
|
||||||
final DeclaredType declaredType = ununi((DeclaredType) returnType);
|
final DeclaredType declaredType = ununi((DeclaredType) returnType);
|
||||||
final TypeElement typeElement = (TypeElement) declaredType.asElement();
|
final TypeElement typeElement = (TypeElement) declaredType.asElement();
|
||||||
final List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
|
final List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
|
||||||
|
@ -925,6 +929,10 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
containerType == null ? null : containerType.getQualifiedName().toString(),
|
containerType == null ? null : containerType.getQualifiedName().toString(),
|
||||||
paramNames,
|
paramNames,
|
||||||
paramTypes,
|
paramTypes,
|
||||||
|
// update/delete/insert query methods must return int or void
|
||||||
|
returnType != null
|
||||||
|
&& returnType.getKind() != TypeKind.DECLARED
|
||||||
|
&& returnType.getKind() != TypeKind.ARRAY,
|
||||||
isNative,
|
isNative,
|
||||||
dao,
|
dao,
|
||||||
sessionType[0],
|
sessionType[0],
|
||||||
|
@ -959,45 +967,11 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
ProcessorSessionFactory.create( context.getProcessingEnvironment() )
|
ProcessorSessionFactory.create( context.getProcessingEnvironment() )
|
||||||
);
|
);
|
||||||
if ( statement != null ) {
|
if ( statement != null ) {
|
||||||
if ( statement instanceof SqmSelectStatement && returnType != null ) {
|
if ( statement instanceof SqmSelectStatement ) {
|
||||||
final SqmSelectStatement<?> select = (SqmSelectStatement<?>) statement;
|
validateSelectHql( method, returnType, mirror, value, (SqmSelectStatement<?>) statement );
|
||||||
final JpaSelection<?> selection = select.getSelection();
|
}
|
||||||
boolean returnTypeCorrect;
|
else {
|
||||||
if ( selection.isCompoundSelection() ) {
|
validateUpdateHql( method, returnType, mirror, value );
|
||||||
switch ( returnType.getKind() ) {
|
|
||||||
case ARRAY:
|
|
||||||
returnTypeCorrect = checkReturnedArrayType((ArrayType) returnType);
|
|
||||||
break;
|
|
||||||
case DECLARED:
|
|
||||||
if ( !checkConstructorReturn( (DeclaredType) returnType, selection ) ) {
|
|
||||||
context.message(method, mirror, value,
|
|
||||||
"return type '" + returnType
|
|
||||||
+ "' of method has no constructor matching query selection list",
|
|
||||||
Diagnostic.Kind.ERROR);
|
|
||||||
}
|
|
||||||
returnTypeCorrect = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
returnTypeCorrect = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( selection instanceof JpaEntityJoin ) {
|
|
||||||
final JpaEntityJoin<?> from = (JpaEntityJoin<?>) selection;
|
|
||||||
returnTypeCorrect = checkReturnedEntity( from.getModel(), returnType );
|
|
||||||
}
|
|
||||||
else if ( selection instanceof JpaRoot ) {
|
|
||||||
final JpaRoot<?> from = (JpaRoot<?>) selection;
|
|
||||||
returnTypeCorrect = checkReturnedEntity( from.getModel(), returnType );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO: anything more we can do here? e.g. check constructor
|
|
||||||
returnTypeCorrect = true;
|
|
||||||
}
|
|
||||||
if ( !returnTypeCorrect ) {
|
|
||||||
context.message(method, mirror, value,
|
|
||||||
"return type of query did not match return type '" + returnType + "' of method",
|
|
||||||
Diagnostic.Kind.ERROR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for ( SqmParameter<?> param : statement.getSqmParameters() ) {
|
for ( SqmParameter<?> param : statement.getSqmParameters() ) {
|
||||||
checkParameter( param, paramNames, paramTypes, method, mirror, value);
|
checkParameter( param, paramNames, paramTypes, method, mirror, value);
|
||||||
|
@ -1005,6 +979,67 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateUpdateHql(
|
||||||
|
ExecutableElement method,
|
||||||
|
@Nullable TypeMirror returnType,
|
||||||
|
AnnotationMirror mirror,
|
||||||
|
AnnotationValue value) {
|
||||||
|
if ( returnType == null
|
||||||
|
|| returnType.getKind() != TypeKind.VOID
|
||||||
|
&& returnType.getKind() != TypeKind.INT ) {
|
||||||
|
context.message( method, mirror, value,
|
||||||
|
"return type of mutation query method must be 'int' or 'void'",
|
||||||
|
Diagnostic.Kind.ERROR );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateSelectHql(
|
||||||
|
ExecutableElement method,
|
||||||
|
@Nullable TypeMirror returnType,
|
||||||
|
AnnotationMirror mirror,
|
||||||
|
AnnotationValue value,
|
||||||
|
SqmSelectStatement<?> statement) {
|
||||||
|
if ( returnType != null ) {
|
||||||
|
final JpaSelection<?> selection = statement.getSelection();
|
||||||
|
boolean returnTypeCorrect;
|
||||||
|
if ( selection.isCompoundSelection() ) {
|
||||||
|
switch ( returnType.getKind() ) {
|
||||||
|
case ARRAY:
|
||||||
|
returnTypeCorrect = checkReturnedArrayType( (ArrayType) returnType );
|
||||||
|
break;
|
||||||
|
case DECLARED:
|
||||||
|
if ( !checkConstructorReturn( (DeclaredType) returnType, selection ) ) {
|
||||||
|
context.message(method, mirror, value,
|
||||||
|
"return type '" + returnType
|
||||||
|
+ "' of method has no constructor matching query selection list",
|
||||||
|
Diagnostic.Kind.ERROR);
|
||||||
|
}
|
||||||
|
returnTypeCorrect = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
returnTypeCorrect = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( selection instanceof JpaEntityJoin ) {
|
||||||
|
final JpaEntityJoin<?> from = (JpaEntityJoin<?>) selection;
|
||||||
|
returnTypeCorrect = checkReturnedEntity( from.getModel(), returnType );
|
||||||
|
}
|
||||||
|
else if ( selection instanceof JpaRoot ) {
|
||||||
|
final JpaRoot<?> from = (JpaRoot<?>) selection;
|
||||||
|
returnTypeCorrect = checkReturnedEntity( from.getModel(), returnType );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: anything more we can do here? e.g. check constructor
|
||||||
|
returnTypeCorrect = true;
|
||||||
|
}
|
||||||
|
if ( !returnTypeCorrect ) {
|
||||||
|
context.message(method, mirror, value,
|
||||||
|
"return type of query did not match return type '" + returnType + "' of method",
|
||||||
|
Diagnostic.Kind.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean checkConstructorReturn(DeclaredType returnType, JpaSelection<?> selection) {
|
private static boolean checkConstructorReturn(DeclaredType returnType, JpaSelection<?> selection) {
|
||||||
final List<? extends JpaSelection<?>> selectionItems = selection.getSelectionItems();
|
final List<? extends JpaSelection<?>> selectionItems = selection.getSelectionItems();
|
||||||
if ( selectionItems == null ) {
|
if ( selectionItems == null ) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
private final String queryString;
|
private final String queryString;
|
||||||
private final @Nullable String returnTypeName;
|
private final @Nullable String returnTypeName;
|
||||||
private final @Nullable String containerTypeName;
|
private final @Nullable String containerTypeName;
|
||||||
|
private final boolean isUpdate;
|
||||||
private final boolean isNative;
|
private final boolean isNative;
|
||||||
|
|
||||||
public QueryMethod(
|
public QueryMethod(
|
||||||
|
@ -36,6 +37,7 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
String containerTypeName,
|
String containerTypeName,
|
||||||
List<String> paramNames,
|
List<String> paramNames,
|
||||||
List<String> paramTypes,
|
List<String> paramTypes,
|
||||||
|
boolean isUpdate,
|
||||||
boolean isNative,
|
boolean isNative,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
|
@ -49,6 +51,7 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
this.queryString = queryString;
|
this.queryString = queryString;
|
||||||
this.returnTypeName = returnTypeName;
|
this.returnTypeName = returnTypeName;
|
||||||
this.containerTypeName = containerTypeName;
|
this.containerTypeName = containerTypeName;
|
||||||
|
this.isUpdate = isUpdate;
|
||||||
this.isNative = isNative;
|
this.isNative = isNative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +84,11 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
parameters( paramTypes, declaration );
|
parameters( paramTypes, declaration );
|
||||||
declaration
|
declaration
|
||||||
.append(" {")
|
.append(" {")
|
||||||
.append("\n\treturn ");
|
.append("\n\t");
|
||||||
|
if ( returnTypeName == null || !returnTypeName.equals("void") ) {
|
||||||
|
declaration
|
||||||
|
.append("return ");
|
||||||
|
}
|
||||||
if ( isNative && returnTypeName != null && containerTypeName == null
|
if ( isNative && returnTypeName != null && containerTypeName == null
|
||||||
&& isUsingEntityManager() ) {
|
&& isUsingEntityManager() ) {
|
||||||
// EntityManager.createNativeQuery() does not return TypedQuery,
|
// EntityManager.createNativeQuery() does not return TypedQuery,
|
||||||
|
@ -95,7 +102,7 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
.append(isNative ? ".createNativeQuery" : ".createQuery")
|
.append(isNative ? ".createNativeQuery" : ".createQuery")
|
||||||
.append("(")
|
.append("(")
|
||||||
.append(getConstantName());
|
.append(getConstantName());
|
||||||
if ( returnTypeName != null ) {
|
if ( returnTypeName != null && !isUpdate ) {
|
||||||
declaration
|
declaration
|
||||||
.append(", ")
|
.append(", ")
|
||||||
.append(annotationMetaEntity.importType(returnTypeName))
|
.append(annotationMetaEntity.importType(returnTypeName))
|
||||||
|
@ -103,7 +110,17 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
}
|
}
|
||||||
declaration.append(")");
|
declaration.append(")");
|
||||||
boolean unwrapped = setParameters( paramTypes, declaration );
|
boolean unwrapped = setParameters( paramTypes, declaration );
|
||||||
if ( containerTypeName == null) {
|
execute( declaration, unwrapped );
|
||||||
|
declaration.append(";\n}");
|
||||||
|
return declaration.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void execute(StringBuilder declaration, boolean unwrapped) {
|
||||||
|
if ( isUpdate ) {
|
||||||
|
declaration
|
||||||
|
.append("\n\t\t\t.executeUpdate()");
|
||||||
|
}
|
||||||
|
else if ( containerTypeName == null) {
|
||||||
declaration
|
declaration
|
||||||
.append("\n\t\t\t.getSingleResult()");
|
.append("\n\t\t\t.getSingleResult()");
|
||||||
}
|
}
|
||||||
|
@ -122,8 +139,6 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
declaration.append(";\n}");
|
|
||||||
return declaration.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean setParameters(List<String> paramTypes, StringBuilder declaration) {
|
private boolean setParameters(List<String> paramTypes, StringBuilder declaration) {
|
||||||
|
|
Loading…
Reference in New Issue