HHH-16633 allow finder and query methods to accept the session type as a parameter
This commit is contained in:
parent
a80224f921
commit
803cd6aa1e
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.jpamodelgen.annotation;
|
package org.hibernate.jpamodelgen.annotation;
|
||||||
|
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
|
||||||
import org.hibernate.jpamodelgen.model.Metamodel;
|
import org.hibernate.jpamodelgen.model.Metamodel;
|
||||||
import org.hibernate.jpamodelgen.util.Constants;
|
import org.hibernate.jpamodelgen.util.Constants;
|
||||||
|
|
||||||
|
@ -19,41 +18,24 @@ import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFr
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractFinderMethod implements MetaAttribute {
|
public abstract class AbstractFinderMethod extends AbstractQueryMethod {
|
||||||
final Metamodel annotationMetaEntity;
|
|
||||||
final String methodName;
|
|
||||||
final String entity;
|
final String entity;
|
||||||
final boolean belongsToDao;
|
|
||||||
final String sessionType;
|
|
||||||
final boolean usingEntityManager;
|
|
||||||
final boolean reactive;
|
|
||||||
private final boolean addNonnullAnnotation;
|
|
||||||
final List<String> fetchProfiles;
|
final List<String> fetchProfiles;
|
||||||
|
|
||||||
final List<String> paramNames;
|
|
||||||
final List<String> paramTypes;
|
|
||||||
|
|
||||||
public AbstractFinderMethod(
|
public AbstractFinderMethod(
|
||||||
Metamodel annotationMetaEntity,
|
Metamodel annotationMetaEntity,
|
||||||
String methodName,
|
String methodName,
|
||||||
String entity,
|
String entity,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
|
String sessionName,
|
||||||
List<String> fetchProfiles,
|
List<String> fetchProfiles,
|
||||||
List<String> paramNames,
|
List<String> paramNames,
|
||||||
List<String> paramTypes,
|
List<String> paramTypes,
|
||||||
boolean addNonnullAnnotation) {
|
boolean addNonnullAnnotation) {
|
||||||
this.annotationMetaEntity = annotationMetaEntity;
|
super( annotationMetaEntity, methodName, paramNames, paramTypes, sessionType, sessionName, belongsToDao, addNonnullAnnotation );
|
||||||
this.methodName = methodName;
|
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.belongsToDao = belongsToDao;
|
|
||||||
this.sessionType = sessionType;
|
|
||||||
this.fetchProfiles = fetchProfiles;
|
this.fetchProfiles = fetchProfiles;
|
||||||
this.paramNames = paramNames;
|
|
||||||
this.paramTypes = paramTypes;
|
|
||||||
this.addNonnullAnnotation = addNonnullAnnotation;
|
|
||||||
this.usingEntityManager = Constants.ENTITY_MANAGER.equals(sessionType);
|
|
||||||
this.reactive = Constants.MUTINY_SESSION.equals(sessionType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,26 +48,11 @@ public abstract class AbstractFinderMethod implements MetaAttribute {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMetaType() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPropertyName() {
|
|
||||||
return methodName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTypeDeclaration() {
|
public String getTypeDeclaration() {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Metamodel getHostingEntity() {
|
|
||||||
return annotationMetaEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract boolean isId();
|
abstract boolean isId();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -104,20 +71,6 @@ public abstract class AbstractFinderMethod implements MetaAttribute {
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parameterList() {
|
|
||||||
return paramTypes.stream()
|
|
||||||
.map(this::strip)
|
|
||||||
.map(annotationMetaEntity::importType)
|
|
||||||
.reduce((x, y) -> x + ',' + y)
|
|
||||||
.orElse("");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String strip(String type) {
|
|
||||||
int index = type.indexOf("<");
|
|
||||||
String stripped = index > 0 ? type.substring(0, index) : type;
|
|
||||||
return type.endsWith("...") ? stripped + "..." : stripped;
|
|
||||||
}
|
|
||||||
|
|
||||||
String constantName() {
|
String constantName() {
|
||||||
return getUpperUnderscoreCaseFromLowerCamelCase(methodName) + "_BY_"
|
return getUpperUnderscoreCaseFromLowerCamelCase(methodName) + "_BY_"
|
||||||
+ paramNames.stream()
|
+ paramNames.stream()
|
||||||
|
@ -212,7 +165,8 @@ public abstract class AbstractFinderMethod implements MetaAttribute {
|
||||||
parameters( declaration) ;
|
parameters( declaration) ;
|
||||||
declaration
|
declaration
|
||||||
.append(" {")
|
.append(" {")
|
||||||
.append("\n\treturn entityManager");
|
.append("\n\treturn ")
|
||||||
|
.append(sessionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void entityType(StringBuilder declaration) {
|
private void entityType(StringBuilder declaration) {
|
||||||
|
@ -237,12 +191,7 @@ public abstract class AbstractFinderMethod implements MetaAttribute {
|
||||||
void parameters(StringBuilder declaration) {
|
void parameters(StringBuilder declaration) {
|
||||||
declaration
|
declaration
|
||||||
.append("(");
|
.append("(");
|
||||||
if ( !belongsToDao ) {
|
sessionParameter( declaration );
|
||||||
notNull( declaration );
|
|
||||||
declaration
|
|
||||||
.append(annotationMetaEntity.importType(Constants.ENTITY_MANAGER))
|
|
||||||
.append(" entityManager");
|
|
||||||
}
|
|
||||||
for ( int i = 0; i < paramNames.size(); i ++ ) {
|
for ( int i = 0; i < paramNames.size(); i ++ ) {
|
||||||
if ( !belongsToDao || i > 0 ) {
|
if ( !belongsToDao || i > 0 ) {
|
||||||
declaration
|
declaration
|
||||||
|
@ -259,13 +208,4 @@ public abstract class AbstractFinderMethod implements MetaAttribute {
|
||||||
declaration
|
declaration
|
||||||
.append(')');
|
.append(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notNull(StringBuilder declaration) {
|
|
||||||
if ( addNonnullAnnotation ) {
|
|
||||||
declaration
|
|
||||||
.append('@')
|
|
||||||
.append(annotationMetaEntity.importType("jakarta.annotation.Nonnull"))
|
|
||||||
.append(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.jpamodelgen.annotation;
|
||||||
|
|
||||||
|
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
||||||
|
import org.hibernate.jpamodelgen.model.Metamodel;
|
||||||
|
import org.hibernate.jpamodelgen.util.Constants;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.hibernate.jpamodelgen.util.Constants.SESSION_TYPES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gavin King
|
||||||
|
*/
|
||||||
|
public abstract class AbstractQueryMethod implements MetaAttribute {
|
||||||
|
final Metamodel annotationMetaEntity;
|
||||||
|
final String methodName;
|
||||||
|
final List<String> paramNames;
|
||||||
|
final List<String> paramTypes;
|
||||||
|
final String sessionType;
|
||||||
|
final String sessionName;
|
||||||
|
final boolean belongsToDao;
|
||||||
|
final boolean usingEntityManager;
|
||||||
|
final boolean reactive;
|
||||||
|
final boolean addNonnullAnnotation;
|
||||||
|
|
||||||
|
public AbstractQueryMethod(
|
||||||
|
Metamodel annotationMetaEntity,
|
||||||
|
String methodName,
|
||||||
|
List<String> paramNames, List<String> paramTypes,
|
||||||
|
String sessionType,
|
||||||
|
String sessionName,
|
||||||
|
boolean belongsToDao,
|
||||||
|
boolean addNonnullAnnotation) {
|
||||||
|
this.annotationMetaEntity = annotationMetaEntity;
|
||||||
|
this.methodName = methodName;
|
||||||
|
this.paramNames = paramNames;
|
||||||
|
this.paramTypes = paramTypes;
|
||||||
|
this.sessionType = sessionType;
|
||||||
|
this.sessionName = sessionName;
|
||||||
|
this.belongsToDao = belongsToDao;
|
||||||
|
this.addNonnullAnnotation = addNonnullAnnotation;
|
||||||
|
this.usingEntityManager = Constants.ENTITY_MANAGER.equals(sessionType);
|
||||||
|
this.reactive = Constants.MUTINY_SESSION.equals(sessionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Metamodel getHostingEntity() {
|
||||||
|
return annotationMetaEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMetaType() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPropertyName() {
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
String parameterList() {
|
||||||
|
return paramTypes.stream()
|
||||||
|
.map(this::strip)
|
||||||
|
.map(annotationMetaEntity::importType)
|
||||||
|
.reduce((x, y) -> x + ',' + y)
|
||||||
|
.orElse("");
|
||||||
|
}
|
||||||
|
|
||||||
|
String strip(String type) {
|
||||||
|
int index = type.indexOf("<");
|
||||||
|
String stripped = index > 0 ? type.substring(0, index) : type;
|
||||||
|
return type.endsWith("...") ? stripped + "..." : stripped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sessionParameter(StringBuilder declaration) {
|
||||||
|
if ( !belongsToDao ) {
|
||||||
|
notNull(declaration);
|
||||||
|
declaration
|
||||||
|
.append(annotationMetaEntity.importType(sessionType))
|
||||||
|
.append(' ')
|
||||||
|
.append(sessionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notNull(StringBuilder declaration) {
|
||||||
|
if ( addNonnullAnnotation ) {
|
||||||
|
declaration
|
||||||
|
.append('@')
|
||||||
|
.append(annotationMetaEntity.importType("jakarta.annotation.Nonnull"))
|
||||||
|
.append(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,7 @@ import static javax.lang.model.util.ElementFilter.fieldsIn;
|
||||||
import static javax.lang.model.util.ElementFilter.methodsIn;
|
import static javax.lang.model.util.ElementFilter.methodsIn;
|
||||||
import static org.hibernate.jpamodelgen.annotation.QueryMethod.isOrderParam;
|
import static org.hibernate.jpamodelgen.annotation.QueryMethod.isOrderParam;
|
||||||
import static org.hibernate.jpamodelgen.annotation.QueryMethod.isPageParam;
|
import static org.hibernate.jpamodelgen.annotation.QueryMethod.isPageParam;
|
||||||
|
import static org.hibernate.jpamodelgen.util.Constants.SESSION_TYPES;
|
||||||
import static org.hibernate.jpamodelgen.util.NullnessUtil.castNonNull;
|
import static org.hibernate.jpamodelgen.util.NullnessUtil.castNonNull;
|
||||||
import static org.hibernate.jpamodelgen.util.TypeUtils.containsAnnotation;
|
import static org.hibernate.jpamodelgen.util.TypeUtils.containsAnnotation;
|
||||||
import static org.hibernate.jpamodelgen.util.TypeUtils.determineAccessTypeForHierarchy;
|
import static org.hibernate.jpamodelgen.util.TypeUtils.determineAccessTypeForHierarchy;
|
||||||
|
@ -494,7 +495,11 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
createCriteriaFinder( method, returnType, containerType, entity );
|
createCriteriaFinder( method, returnType, containerType, entity );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch ( method.getParameters().size() ) {
|
final long parameterCount =
|
||||||
|
method.getParameters().stream()
|
||||||
|
.filter(AnnotationMetaEntity::isFinderParameterMappingToAttribute)
|
||||||
|
.count();
|
||||||
|
switch ( (int) parameterCount ) {
|
||||||
case 0:
|
case 0:
|
||||||
context.message( method, "missing parameter", Diagnostic.Kind.ERROR );
|
context.message( method, "missing parameter", Diagnostic.Kind.ERROR );
|
||||||
break;
|
break;
|
||||||
|
@ -517,9 +522,13 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
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 );
|
||||||
|
removeSessionFromParameters(paramNames, paramTypes);
|
||||||
final String methodKey = methodName + paramTypes;
|
final String methodKey = methodName + paramTypes;
|
||||||
for ( VariableElement param : method.getParameters() ) {
|
for ( VariableElement param : method.getParameters() ) {
|
||||||
validateFinderParameter(entity, param );
|
if ( isFinderParameterMappingToAttribute( param ) ) {
|
||||||
|
validateFinderParameter( entity, param );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
putMember( methodKey,
|
putMember( methodKey,
|
||||||
new CriteriaFinderMethod(
|
new CriteriaFinderMethod(
|
||||||
|
@ -531,13 +540,40 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
paramTypes,
|
paramTypes,
|
||||||
false,
|
false,
|
||||||
dao,
|
dao,
|
||||||
sessionType,
|
sessionType[0],
|
||||||
|
sessionType[1],
|
||||||
enabledFetchProfiles( method ),
|
enabledFetchProfiles( method ),
|
||||||
context.addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isFinderParameterMappingToAttribute(VariableElement param) {
|
||||||
|
return !SESSION_TYPES.contains(param.asType().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void removeSessionFromParameters(List<String> paramNames, List<String> paramTypes) {
|
||||||
|
for ( int i = 0; i < paramNames.size(); i ++ ) {
|
||||||
|
final String type = paramTypes.get(i);
|
||||||
|
if ( SESSION_TYPES.contains(type) ) {
|
||||||
|
paramNames.remove(i);
|
||||||
|
paramTypes.remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] sessionTypeFromParameters(List<String> paramNames, List<String> paramTypes) {
|
||||||
|
for ( int i = 0; i < paramNames.size(); i ++ ) {
|
||||||
|
final String type = paramTypes.get(i);
|
||||||
|
final String name = paramNames.get(i);
|
||||||
|
if ( SESSION_TYPES.contains(type) ) {
|
||||||
|
return new String[] { type, name };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String[] { sessionType, "entityManager" };
|
||||||
|
}
|
||||||
|
|
||||||
private static List<String> enabledFetchProfiles(ExecutableElement method) {
|
private static List<String> enabledFetchProfiles(ExecutableElement method) {
|
||||||
final Object enabledFetchProfiles =
|
final Object enabledFetchProfiles =
|
||||||
getAnnotationValue( castNonNull( getAnnotationMirror( method, Constants.FIND ) ),
|
getAnnotationValue( castNonNull( getAnnotationMirror( method, Constants.FIND ) ),
|
||||||
|
@ -560,8 +596,10 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
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 );
|
||||||
|
removeSessionFromParameters( paramNames, paramTypes );
|
||||||
final String methodKey = methodName + paramTypes;
|
final String methodKey = methodName + paramTypes;
|
||||||
if ( !usingStatelessSession() // no byNaturalId() lookup API for SS
|
if ( !usingStatelessSession(sessionType[0]) // no byNaturalId() lookup API for SS
|
||||||
&& matchesNaturalKey( method, entity ) ) {
|
&& matchesNaturalKey( method, entity ) ) {
|
||||||
putMember( methodKey,
|
putMember( methodKey,
|
||||||
new NaturalIdFinderMethod(
|
new NaturalIdFinderMethod(
|
||||||
|
@ -571,7 +609,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
paramNames,
|
paramNames,
|
||||||
paramTypes,
|
paramTypes,
|
||||||
dao,
|
dao,
|
||||||
sessionType,
|
sessionType[0],
|
||||||
|
sessionType[1],
|
||||||
enabledFetchProfiles( method ),
|
enabledFetchProfiles( method ),
|
||||||
context.addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
)
|
)
|
||||||
|
@ -588,7 +627,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
paramTypes,
|
paramTypes,
|
||||||
false,
|
false,
|
||||||
dao,
|
dao,
|
||||||
sessionType,
|
sessionType[0],
|
||||||
|
sessionType[1],
|
||||||
enabledFetchProfiles( method ),
|
enabledFetchProfiles( method ),
|
||||||
context.addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
)
|
)
|
||||||
|
@ -598,22 +638,30 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
|
|
||||||
private void createSingleParameterFinder(ExecutableElement method, TypeMirror returnType, TypeElement entity) {
|
private void createSingleParameterFinder(ExecutableElement method, TypeMirror returnType, TypeElement entity) {
|
||||||
final String methodName = method.getSimpleName().toString();
|
final String methodName = method.getSimpleName().toString();
|
||||||
final VariableElement parameter = method.getParameters().get(0);
|
final VariableElement parameter =
|
||||||
|
method.getParameters().stream()
|
||||||
|
.filter(AnnotationMetaEntity::isFinderParameterMappingToAttribute)
|
||||||
|
.findFirst().orElseThrow();
|
||||||
|
final List<String> paramNames = parameterNames(method);
|
||||||
|
final List<String> paramTypes = parameterTypes(method);
|
||||||
|
final String[] sessionType = sessionTypeFromParameters( paramNames, paramTypes );
|
||||||
|
removeSessionFromParameters(paramNames, paramTypes);
|
||||||
final FieldType fieldType = validateFinderParameter( entity, parameter );
|
final FieldType fieldType = validateFinderParameter( entity, parameter );
|
||||||
if ( fieldType != null ) {
|
if ( fieldType != null ) {
|
||||||
final String methodKey = methodName + "!";
|
final String methodKey = methodName + "!";
|
||||||
final List<String> profiles = enabledFetchProfiles( method );
|
final List<String> profiles = enabledFetchProfiles( method );
|
||||||
switch ( pickStrategy( fieldType, profiles ) ) {
|
switch ( pickStrategy( fieldType, sessionType[0], profiles ) ) {
|
||||||
case ID:
|
case ID:
|
||||||
putMember( methodKey,
|
putMember( methodKey,
|
||||||
new IdFinderMethod(
|
new IdFinderMethod(
|
||||||
this,
|
this,
|
||||||
methodName,
|
methodName,
|
||||||
returnType.toString(),
|
returnType.toString(),
|
||||||
parameter.getSimpleName().toString(),
|
paramNames.get(0),
|
||||||
parameter.asType().toString(),
|
paramTypes.get(0),
|
||||||
dao,
|
dao,
|
||||||
sessionType,
|
sessionType[0],
|
||||||
|
sessionType[1],
|
||||||
profiles,
|
profiles,
|
||||||
context.addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
)
|
)
|
||||||
|
@ -625,10 +673,11 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
this,
|
this,
|
||||||
methodName,
|
methodName,
|
||||||
returnType.toString(),
|
returnType.toString(),
|
||||||
List.of( parameter.getSimpleName().toString() ),
|
paramNames,
|
||||||
List.of( parameter.asType().toString() ),
|
paramTypes,
|
||||||
dao,
|
dao,
|
||||||
sessionType,
|
sessionType[0],
|
||||||
|
sessionType[1],
|
||||||
profiles,
|
profiles,
|
||||||
context.addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
)
|
)
|
||||||
|
@ -641,11 +690,12 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
methodName,
|
methodName,
|
||||||
returnType.toString(),
|
returnType.toString(),
|
||||||
null,
|
null,
|
||||||
List.of( parameter.getSimpleName().toString() ),
|
paramNames,
|
||||||
List.of( parameter.asType().toString() ),
|
paramTypes,
|
||||||
fieldType == FieldType.ID,
|
fieldType == FieldType.ID,
|
||||||
dao,
|
dao,
|
||||||
sessionType,
|
sessionType[0],
|
||||||
|
sessionType[1],
|
||||||
profiles,
|
profiles,
|
||||||
context.addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
)
|
)
|
||||||
|
@ -655,16 +705,16 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FieldType pickStrategy(FieldType fieldType, List<String> profiles) {
|
private FieldType pickStrategy(FieldType fieldType, String sessionType, List<String> profiles) {
|
||||||
switch (fieldType) {
|
switch (fieldType) {
|
||||||
case ID:
|
case ID:
|
||||||
// no byId() API for SS or M.S, only get()
|
// no byId() API for SS or M.S, only get()
|
||||||
return (usingStatelessSession() || usingReactiveSession()) && !profiles.isEmpty()
|
return (usingStatelessSession(sessionType) || usingReactiveSession(sessionType)) && !profiles.isEmpty()
|
||||||
? FieldType.BASIC : FieldType.ID;
|
? FieldType.BASIC : FieldType.ID;
|
||||||
case NATURAL_ID:
|
case NATURAL_ID:
|
||||||
// no byNaturalId() lookup API for SS
|
// no byNaturalId() lookup API for SS
|
||||||
// no byNaturalId() in M.S, but we do have Identifier workaround
|
// no byNaturalId() in M.S, but we do have Identifier workaround
|
||||||
return usingStatelessSession() || (usingReactiveSession() && !profiles.isEmpty())
|
return usingStatelessSession(sessionType) || (usingReactiveSession(sessionType) && !profiles.isEmpty())
|
||||||
? FieldType.BASIC : FieldType.NATURAL_ID;
|
? FieldType.BASIC : FieldType.NATURAL_ID;
|
||||||
default:
|
default:
|
||||||
return FieldType.BASIC;
|
return FieldType.BASIC;
|
||||||
|
@ -673,12 +723,14 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
|
|
||||||
private boolean matchesNaturalKey(ExecutableElement method, TypeElement entity) {
|
private boolean matchesNaturalKey(ExecutableElement method, TypeElement entity) {
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
List<? extends VariableElement> parameters = method.getParameters();
|
final List<? extends VariableElement> parameters = method.getParameters();
|
||||||
for ( VariableElement param : parameters) {
|
for ( VariableElement param : parameters ) {
|
||||||
if ( validateFinderParameter( entity, param ) != FieldType.NATURAL_ID ) {
|
if ( isFinderParameterMappingToAttribute( param ) ) {
|
||||||
// no short-circuit here because we want to validate
|
if ( validateFinderParameter( entity, param ) != FieldType.NATURAL_ID ) {
|
||||||
// all of them and get the nice error report
|
// no short-circuit here because we want to validate
|
||||||
result = false;
|
// all of them and get the nice error report
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result && countNaturalIdFields( entity ) == parameters.size() ;
|
return result && countNaturalIdFields( entity ) == parameters.size() ;
|
||||||
|
@ -781,7 +833,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
final String hql = (String) query;
|
final String hql = (String) query;
|
||||||
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 );
|
||||||
|
removeSessionFromParameters(paramNames, paramTypes);
|
||||||
final QueryMethod attribute =
|
final QueryMethod attribute =
|
||||||
new QueryMethod(
|
new QueryMethod(
|
||||||
this,
|
this,
|
||||||
|
@ -793,7 +846,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
paramTypes,
|
paramTypes,
|
||||||
isNative,
|
isNative,
|
||||||
dao,
|
dao,
|
||||||
sessionType,
|
sessionType[0],
|
||||||
|
sessionType[1],
|
||||||
context.addNonnullAnnotation()
|
context.addNonnullAnnotation()
|
||||||
);
|
);
|
||||||
putMember( attribute.getPropertyName() + paramTypes, attribute );
|
putMember( attribute.getPropertyName() + paramTypes, attribute );
|
||||||
|
@ -923,11 +977,11 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
&& !isOrderParam(type);
|
&& !isOrderParam(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean usingReactiveSession() {
|
private boolean usingReactiveSession(String sessionType) {
|
||||||
return Constants.MUTINY_SESSION.equals(sessionType);
|
return Constants.MUTINY_SESSION.equals(sessionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean usingStatelessSession() {
|
private boolean usingStatelessSession(String sessionType) {
|
||||||
return Constants.HIB_STATELESS_SESSION.equals(sessionType);
|
return Constants.HIB_STATELESS_SESSION.equals(sessionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,10 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
boolean isId,
|
boolean isId,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
|
String sessionName,
|
||||||
List<String> fetchProfiles,
|
List<String> fetchProfiles,
|
||||||
boolean addNonnullAnnotation) {
|
boolean addNonnullAnnotation) {
|
||||||
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, fetchProfiles,
|
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
|
||||||
paramNames, paramTypes, addNonnullAnnotation );
|
paramNames, paramTypes, addNonnullAnnotation );
|
||||||
this.containerType = containerType;
|
this.containerType = containerType;
|
||||||
this.isId = isId;
|
this.isId = isId;
|
||||||
|
@ -61,7 +62,8 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
.append(" == null) throw new IllegalArgumentException(\"Null identifier\");");
|
.append(" == null) throw new IllegalArgumentException(\"Null identifier\");");
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
.append("\n\tvar builder = entityManager")
|
.append("\n\tvar builder = ")
|
||||||
|
.append(sessionName)
|
||||||
.append(usingEntityManager
|
.append(usingEntityManager
|
||||||
? ".getEntityManagerFactory()"
|
? ".getEntityManagerFactory()"
|
||||||
: ".getFactory()")
|
: ".getFactory()")
|
||||||
|
@ -104,7 +106,9 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
.append("\n\t);")
|
.append("\n\t);")
|
||||||
.append("\n\treturn entityManager.createQuery(query)");
|
.append("\n\treturn ")
|
||||||
|
.append(sessionName)
|
||||||
|
.append(".createQuery(query)");
|
||||||
final boolean hasEnabledFetchProfiles = !fetchProfiles.isEmpty();
|
final boolean hasEnabledFetchProfiles = !fetchProfiles.isEmpty();
|
||||||
final boolean hasNativeReturnType = containerType != null && containerType.startsWith("org.hibernate");
|
final boolean hasNativeReturnType = containerType != null && containerType.startsWith("org.hibernate");
|
||||||
final boolean unwrap =
|
final boolean unwrap =
|
||||||
|
|
|
@ -25,9 +25,10 @@ public class IdFinderMethod extends AbstractFinderMethod {
|
||||||
String paramName, String paramType,
|
String paramName, String paramType,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
|
String sessionName,
|
||||||
List<String> fetchProfiles,
|
List<String> fetchProfiles,
|
||||||
boolean addNonnullAnnotation) {
|
boolean addNonnullAnnotation) {
|
||||||
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, fetchProfiles,
|
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
|
||||||
List.of(paramName), List.of(paramType), addNonnullAnnotation );
|
List.of(paramName), List.of(paramType), addNonnullAnnotation );
|
||||||
this.paramName = paramName;
|
this.paramName = paramName;
|
||||||
usingStatelessSession = Constants.HIB_STATELESS_SESSION.equals(sessionType);
|
usingStatelessSession = Constants.HIB_STATELESS_SESSION.equals(sessionType);
|
||||||
|
|
|
@ -21,9 +21,10 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
|
||||||
List<String> paramNames, List<String> paramTypes,
|
List<String> paramNames, List<String> paramTypes,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
|
String sessionName,
|
||||||
List<String> fetchProfiles,
|
List<String> fetchProfiles,
|
||||||
boolean addNonnullAnnotation) {
|
boolean addNonnullAnnotation) {
|
||||||
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, fetchProfiles,
|
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
|
||||||
paramNames, paramTypes, addNonnullAnnotation );
|
paramNames, paramTypes, addNonnullAnnotation );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.jpamodelgen.annotation;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.jpamodelgen.model.MetaAttribute;
|
|
||||||
import org.hibernate.jpamodelgen.model.Metamodel;
|
import org.hibernate.jpamodelgen.model.Metamodel;
|
||||||
import org.hibernate.jpamodelgen.util.Constants;
|
import org.hibernate.jpamodelgen.util.Constants;
|
||||||
import org.hibernate.query.Order;
|
import org.hibernate.query.Order;
|
||||||
|
@ -22,19 +21,11 @@ import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFr
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class QueryMethod implements MetaAttribute {
|
public class QueryMethod extends AbstractQueryMethod {
|
||||||
private final Metamodel annotationMetaEntity;
|
|
||||||
private final String methodName;
|
|
||||||
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 List<String> paramNames;
|
|
||||||
private final List<String> paramTypes;
|
|
||||||
private final boolean isNative;
|
private final boolean isNative;
|
||||||
private final boolean belongsToDao;
|
|
||||||
private final boolean usingEntityManager;
|
|
||||||
private final boolean reactive;
|
|
||||||
private final boolean addNonnullAnnotation;
|
|
||||||
|
|
||||||
public QueryMethod(
|
public QueryMethod(
|
||||||
Metamodel annotationMetaEntity,
|
Metamodel annotationMetaEntity,
|
||||||
|
@ -49,19 +40,13 @@ public class QueryMethod implements MetaAttribute {
|
||||||
boolean isNative,
|
boolean isNative,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
|
String sessionName,
|
||||||
boolean addNonnullAnnotation) {
|
boolean addNonnullAnnotation) {
|
||||||
this.annotationMetaEntity = annotationMetaEntity;
|
super( annotationMetaEntity, methodName, paramNames, paramTypes, sessionType, sessionName, belongsToDao, addNonnullAnnotation );
|
||||||
this.methodName = methodName;
|
|
||||||
this.queryString = queryString;
|
this.queryString = queryString;
|
||||||
this.returnTypeName = returnTypeName;
|
this.returnTypeName = returnTypeName;
|
||||||
this.containerTypeName = containerTypeName;
|
this.containerTypeName = containerTypeName;
|
||||||
this.paramNames = paramNames;
|
|
||||||
this.paramTypes = paramTypes;
|
|
||||||
this.isNative = isNative;
|
this.isNative = isNative;
|
||||||
this.belongsToDao = belongsToDao;
|
|
||||||
this.addNonnullAnnotation = addNonnullAnnotation;
|
|
||||||
this.usingEntityManager = Constants.ENTITY_MANAGER.equals(sessionType);
|
|
||||||
this.reactive = Constants.MUTINY_SESSION.equals(sessionType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -98,8 +83,8 @@ public class QueryMethod implements MetaAttribute {
|
||||||
.append(") ");
|
.append(") ");
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
.append("entityManager.")
|
.append(sessionName)
|
||||||
.append(isNative ? "createNativeQuery" : "createQuery")
|
.append(isNative ? ".createNativeQuery" : ".createQuery")
|
||||||
.append("(")
|
.append("(")
|
||||||
.append(getConstantName());
|
.append(getConstantName());
|
||||||
if ( returnTypeName != null ) {
|
if ( returnTypeName != null ) {
|
||||||
|
@ -210,30 +195,22 @@ public class QueryMethod implements MetaAttribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parameters(List<String> paramTypes, StringBuilder declaration) {
|
private void parameters(List<String> paramTypes, StringBuilder declaration) {
|
||||||
declaration.append("(");
|
declaration
|
||||||
if ( !belongsToDao ) {
|
.append("(");
|
||||||
notNull( declaration );
|
sessionParameter( declaration );
|
||||||
declaration
|
for ( int i = 0; i < paramNames.size(); i++ ) {
|
||||||
.append(annotationMetaEntity.importType(Constants.ENTITY_MANAGER))
|
if ( !belongsToDao || i > 0 ) {
|
||||||
.append(" entityManager");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i<paramNames.size(); i++ ) {
|
|
||||||
String ptype = paramTypes.get(i);
|
|
||||||
String param = paramNames.get(i);
|
|
||||||
String rptype = returnTypeName != null
|
|
||||||
? ptype.replace(returnTypeName, annotationMetaEntity.importType(returnTypeName))
|
|
||||||
: ptype;
|
|
||||||
|
|
||||||
if ( !belongsToDao || i>0 ) {
|
|
||||||
declaration
|
declaration
|
||||||
.append(", ");
|
.append(", ");
|
||||||
}
|
}
|
||||||
|
final String type = paramTypes.get(i);
|
||||||
|
final String paramType = returnTypeName != null
|
||||||
|
? type.replace(returnTypeName, annotationMetaEntity.importType(returnTypeName))
|
||||||
|
: type;
|
||||||
declaration
|
declaration
|
||||||
.append(annotationMetaEntity.importType(rptype))
|
.append(annotationMetaEntity.importType(paramType))
|
||||||
.append(" ")
|
.append(" ")
|
||||||
.append(param);
|
.append(paramNames.get(i));
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
.append(")");
|
.append(")");
|
||||||
|
@ -301,20 +278,6 @@ public class QueryMethod implements MetaAttribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parameterList() {
|
|
||||||
return paramTypes.stream()
|
|
||||||
.map(this::strip)
|
|
||||||
.map(annotationMetaEntity::importType)
|
|
||||||
.reduce((x, y) -> x + ',' + y)
|
|
||||||
.orElse("");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String strip(String type) {
|
|
||||||
int index = type.indexOf("<");
|
|
||||||
String stripped = index > 0 ? type.substring(0, index) : type;
|
|
||||||
return type.endsWith("...") ? stripped + "..." : stripped;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isPageParam(String parameterType) {
|
static boolean isPageParam(String parameterType) {
|
||||||
return Page.class.getName().equals(parameterType);
|
return Page.class.getName().equals(parameterType);
|
||||||
}
|
}
|
||||||
|
@ -359,32 +322,7 @@ public class QueryMethod implements MetaAttribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notNull(StringBuilder declaration) {
|
|
||||||
if ( addNonnullAnnotation ) {
|
|
||||||
declaration
|
|
||||||
.append('@')
|
|
||||||
.append(annotationMetaEntity.importType("jakarta.annotation.Nonnull"))
|
|
||||||
.append(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMetaType() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPropertyName() {
|
|
||||||
return methodName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTypeDeclaration() {
|
public String getTypeDeclaration() {
|
||||||
return Constants.QUERY;
|
return Constants.QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Metamodel getHostingEntity() {
|
|
||||||
return annotationMetaEntity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,14 @@ public final class Constants {
|
||||||
java.util.SortedMap.class.getName(), Constants.MAP_ATTRIBUTE
|
java.util.SortedMap.class.getName(), Constants.MAP_ATTRIBUTE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static final Set<String> SESSION_TYPES =
|
||||||
|
Set.of(
|
||||||
|
Constants.ENTITY_MANAGER,
|
||||||
|
Constants.HIB_SESSION,
|
||||||
|
Constants.HIB_STATELESS_SESSION,
|
||||||
|
Constants.MUTINY_SESSION
|
||||||
|
);
|
||||||
|
|
||||||
//TODO: this is not even an exhaustive list of built-in basic types
|
//TODO: this is not even an exhaustive list of built-in basic types
|
||||||
// so any logic that relies on incomplete this list is broken!
|
// so any logic that relies on incomplete this list is broken!
|
||||||
public static final Set<String> BASIC_TYPES = Set.of(
|
public static final Set<String> BASIC_TYPES = Set.of(
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.hibernate.jpamodelgen.test.hqlsql;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.TypedQuery;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.StatelessSession;
|
||||||
|
import org.hibernate.annotations.processing.Find;
|
||||||
|
import org.hibernate.annotations.processing.HQL;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class Books {
|
||||||
|
@Find
|
||||||
|
abstract Book getBook(EntityManager entityManager, String isbn);
|
||||||
|
|
||||||
|
@Find
|
||||||
|
abstract Book getBook(StatelessSession session, String title, String isbn);
|
||||||
|
|
||||||
|
@Find
|
||||||
|
abstract Book getBookByNaturalKey(Session session, String authorName, String title);
|
||||||
|
|
||||||
|
@HQL("from Book where title like ?1")
|
||||||
|
abstract TypedQuery<Book> findByTitle(EntityManager entityManager, String title);
|
||||||
|
|
||||||
|
@HQL("from Book where title like ?1 order by title fetch first ?2 rows only")
|
||||||
|
abstract List<Book> findFirstNByTitle(Session session, String title, int N);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -18,10 +18,12 @@ import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassG
|
||||||
*/
|
*/
|
||||||
public class QueryMethodTest extends CompilationTest {
|
public class QueryMethodTest extends CompilationTest {
|
||||||
@Test
|
@Test
|
||||||
@WithClasses({ Book.class, Dao.class })
|
@WithClasses({ Book.class, Dao.class, Books.class })
|
||||||
public void testQueryMethod() {
|
public void testQueryMethod() {
|
||||||
System.out.println( TestUtil.getMetaModelSourceAsString( Dao.class ) );
|
System.out.println( TestUtil.getMetaModelSourceAsString( Dao.class ) );
|
||||||
|
System.out.println( TestUtil.getMetaModelSourceAsString( Books.class ) );
|
||||||
assertMetamodelClassGeneratedFor( Book.class );
|
assertMetamodelClassGeneratedFor( Book.class );
|
||||||
assertMetamodelClassGeneratedFor( Dao.class );
|
assertMetamodelClassGeneratedFor( Dao.class );
|
||||||
|
assertMetamodelClassGeneratedFor( Books.class );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue