improved reasoning around nullability of finder method parameters
This commit is contained in:
parent
64216dd2c9
commit
7634795f83
|
@ -100,9 +100,9 @@ But it's something to watch out for.
|
||||||
|
|
||||||
If you're completely new to Hibernate and JPA, you might already be wondering how the persistence-related code is structured.
|
If you're completely new to Hibernate and JPA, you might already be wondering how the persistence-related code is structured.
|
||||||
|
|
||||||
Well, typically, your persistence-related code comes in two layers:
|
Well, typically, our persistence-related code comes in two layers:
|
||||||
|
|
||||||
. a representation of your data model in Java, which takes the form of a set of annotated entity classes, and
|
. a representation of our data model in Java, which takes the form of a set of annotated entity classes, and
|
||||||
. a larger number of functions which interact with Hibernate's APIs to perform the persistence operations associated with your various transactions.
|
. a larger number of functions which interact with Hibernate's APIs to perform the persistence operations associated with your various transactions.
|
||||||
|
|
||||||
The first part, the data or "domain" model, is usually easier to write, but doing a great and very clean job of it will strongly affect your success in the second part.
|
The first part, the data or "domain" model, is usually easier to write, but doing a great and very clean job of it will strongly affect your success in the second part.
|
||||||
|
|
|
@ -12,7 +12,6 @@ import org.hibernate.jpamodelgen.util.Constants;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import static org.hibernate.internal.util.StringHelper.qualifier;
|
|
||||||
import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase;
|
import static org.hibernate.jpamodelgen.util.StringUtil.getUpperUnderscoreCaseFromLowerCamelCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,8 +56,6 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract boolean isId();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAttributeNameDeclarationString() {
|
public String getAttributeNameDeclarationString() {
|
||||||
return new StringBuilder()
|
return new StringBuilder()
|
||||||
|
@ -131,6 +128,11 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
|
||||||
.append("\n **/\n");
|
.append("\n **/\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String qualifier(String name) {
|
||||||
|
final int index = name.indexOf('$');
|
||||||
|
return index > 0 ? name.substring(0, index) : name;
|
||||||
|
}
|
||||||
|
|
||||||
void unwrapSession(StringBuilder declaration) {
|
void unwrapSession(StringBuilder declaration) {
|
||||||
if ( isUsingEntityManager() ) {
|
if ( isUsingEntityManager() ) {
|
||||||
declaration
|
declaration
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.hibernate.jpamodelgen.util.Constants;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.hibernate.jpamodelgen.util.Constants.SESSION_TYPES;
|
import static org.hibernate.jpamodelgen.util.Constants.SESSION_TYPES;
|
||||||
|
import static org.hibernate.jpamodelgen.util.TypeUtils.isPrimitive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
|
@ -64,7 +65,7 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|
||||||
return methodName;
|
return methodName;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract boolean isId();
|
abstract boolean isNullable(int index);
|
||||||
|
|
||||||
String parameterList() {
|
String parameterList() {
|
||||||
return paramTypes.stream()
|
return paramTypes.stream()
|
||||||
|
@ -90,7 +91,8 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|
||||||
.append(", ");
|
.append(", ");
|
||||||
}
|
}
|
||||||
final String paramType = paramTypes.get(i);
|
final String paramType = paramTypes.get(i);
|
||||||
if ( isId() || isSessionParameter(paramType) ) {
|
if ( !isNullable(i) && !isPrimitive(paramType)
|
||||||
|
|| isSessionParameter(paramType) ) {
|
||||||
notNull( declaration );
|
notNull( declaration );
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||||
|
|
||||||
import static java.beans.Introspector.decapitalize;
|
import static java.beans.Introspector.decapitalize;
|
||||||
|
import static java.lang.Boolean.FALSE;
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
import static javax.lang.model.util.ElementFilter.fieldsIn;
|
import static javax.lang.model.util.ElementFilter.fieldsIn;
|
||||||
|
@ -545,7 +546,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
containerType == null ? null : containerType.toString(),
|
containerType == null ? null : containerType.toString(),
|
||||||
paramNames,
|
paramNames,
|
||||||
paramTypes,
|
paramTypes,
|
||||||
false,
|
parameterNullability(method, entity),
|
||||||
dao,
|
dao,
|
||||||
sessionType[0],
|
sessionType[0],
|
||||||
sessionType[1],
|
sessionType[1],
|
||||||
|
@ -603,6 +604,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
returnType.toString(),
|
returnType.toString(),
|
||||||
paramNames,
|
paramNames,
|
||||||
paramTypes,
|
paramTypes,
|
||||||
|
parameterNullability(method, entity),
|
||||||
dao,
|
dao,
|
||||||
sessionType[0],
|
sessionType[0],
|
||||||
sessionType[1],
|
sessionType[1],
|
||||||
|
@ -620,7 +622,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
null,
|
null,
|
||||||
paramNames,
|
paramNames,
|
||||||
paramTypes,
|
paramTypes,
|
||||||
false,
|
parameterNullability(method, entity),
|
||||||
dao,
|
dao,
|
||||||
sessionType[0],
|
sessionType[0],
|
||||||
sessionType[1],
|
sessionType[1],
|
||||||
|
@ -669,6 +671,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
returnType.toString(),
|
returnType.toString(),
|
||||||
paramNames,
|
paramNames,
|
||||||
paramTypes,
|
paramTypes,
|
||||||
|
parameterNullability(method, entity),
|
||||||
dao,
|
dao,
|
||||||
sessionType[0],
|
sessionType[0],
|
||||||
sessionType[1],
|
sessionType[1],
|
||||||
|
@ -686,7 +689,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
null,
|
null,
|
||||||
paramNames,
|
paramNames,
|
||||||
paramTypes,
|
paramTypes,
|
||||||
fieldType == FieldType.ID,
|
parameterNullability(method, entity),
|
||||||
dao,
|
dao,
|
||||||
sessionType[0],
|
sessionType[0],
|
||||||
sessionType[1],
|
sessionType[1],
|
||||||
|
@ -746,22 +749,29 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable FieldType validateFinderParameter(TypeElement entity, VariableElement param) {
|
private @Nullable FieldType validateFinderParameter(TypeElement entityType, VariableElement param) {
|
||||||
final AccessType accessType = getAccessType(entity);
|
final Element member = memberMatchingParameter(entityType, param);
|
||||||
for ( Element member : entity.getEnclosedElements() ) {
|
if ( member != null) {
|
||||||
if ( fieldMatchesParameter( entity, param, member, accessType ) ) {
|
final String memberType = memberType( member ).toString();
|
||||||
if ( containsAnnotation( member, Constants.ID, Constants.EMBEDDED_ID ) ) {
|
final String paramType = param.asType().toString();
|
||||||
return FieldType.ID;
|
if ( !isLegalAssignment( paramType, memberType ) ) {
|
||||||
}
|
context.message( param,
|
||||||
else if ( containsAnnotation( member, Constants.NATURAL_ID ) ) {
|
"matching field has type '" + memberType
|
||||||
return FieldType.NATURAL_ID;
|
+ "' in entity class '" + entityType + "'",
|
||||||
}
|
Diagnostic.Kind.ERROR );
|
||||||
else {
|
}
|
||||||
return FieldType.BASIC;
|
|
||||||
}
|
if ( containsAnnotation( member, Constants.ID, Constants.EMBEDDED_ID ) ) {
|
||||||
|
return FieldType.ID;
|
||||||
|
}
|
||||||
|
else if ( containsAnnotation( member, Constants.NATURAL_ID ) ) {
|
||||||
|
return FieldType.NATURAL_ID;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return FieldType.BASIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final AnnotationMirror idClass = getAnnotationMirror( entity, Constants.ID_CLASS );
|
final AnnotationMirror idClass = getAnnotationMirror( entityType, Constants.ID_CLASS );
|
||||||
if ( idClass != null ) {
|
if ( idClass != null ) {
|
||||||
final Object value = getAnnotationValue( idClass, "value" );
|
final Object value = getAnnotationValue( idClass, "value" );
|
||||||
if ( value instanceof TypeMirror ) {
|
if ( value instanceof TypeMirror ) {
|
||||||
|
@ -773,11 +783,16 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
context.message( param,
|
context.message( param,
|
||||||
"no matching field named '"
|
"no matching field named '"
|
||||||
+ param.getSimpleName().toString().replace('$', '.')
|
+ param.getSimpleName().toString().replace('$', '.')
|
||||||
+ "' in entity class '" + entity + "'",
|
+ "' in entity class '" + entityType + "'",
|
||||||
Diagnostic.Kind.ERROR );
|
Diagnostic.Kind.ERROR );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean finderParameterNullable(TypeElement entity, VariableElement param) {
|
||||||
|
final Element member = memberMatchingParameter(entity, param);
|
||||||
|
return member == null || isNullable(member);
|
||||||
|
}
|
||||||
|
|
||||||
private AccessType getAccessType(TypeElement entity) {
|
private AccessType getAccessType(TypeElement entity) {
|
||||||
final String entityClassName = entity.getQualifiedName().toString();
|
final String entityClassName = entity.getQualifiedName().toString();
|
||||||
determineAccessTypeForHierarchy(entity, context );
|
determineAccessTypeForHierarchy(entity, context );
|
||||||
|
@ -794,67 +809,66 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fieldMatchesParameter(TypeElement entityType, VariableElement param, Element member, AccessType accessType) {
|
private @Nullable Element memberMatchingParameter(TypeElement entityType, VariableElement param) {
|
||||||
final StringTokenizer tokens = new StringTokenizer( param.getSimpleName().toString(), "$" );
|
final StringTokenizer tokens = new StringTokenizer( param.getSimpleName().toString(), "$" );
|
||||||
return fieldMatchesParameter( entityType, param, member, accessType, tokens, tokens.nextToken() );
|
return memberMatchingParameter( entityType, param, tokens );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fieldMatchesParameter(
|
private @Nullable Element memberMatchingParameter(TypeElement entityType, VariableElement param, StringTokenizer tokens) {
|
||||||
|
final AccessType accessType = getAccessType(entityType);
|
||||||
|
final String nextToken = tokens.nextToken();
|
||||||
|
for ( Element member : entityType.getEnclosedElements() ) {
|
||||||
|
final Element match =
|
||||||
|
memberMatchingParameter(entityType, param, member, accessType, tokens, nextToken);
|
||||||
|
if ( match != null ) {
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nullable Element memberMatchingParameter(
|
||||||
TypeElement entityType,
|
TypeElement entityType,
|
||||||
VariableElement param,
|
VariableElement param,
|
||||||
Element member,
|
Element candidate,
|
||||||
AccessType accessType,
|
AccessType accessType,
|
||||||
StringTokenizer tokens,
|
StringTokenizer tokens,
|
||||||
String token) {
|
String token) {
|
||||||
final Name memberName = member.getSimpleName();
|
final Name memberName = candidate.getSimpleName();
|
||||||
final TypeMirror type;
|
final TypeMirror type;
|
||||||
if ( accessType == AccessType.FIELD && member.getKind() == ElementKind.FIELD ) {
|
if ( accessType == AccessType.FIELD && candidate.getKind() == ElementKind.FIELD ) {
|
||||||
if ( !fieldMatches(token, memberName) ) {
|
if ( !fieldMatches(token, memberName) ) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
type = member.asType();
|
type = candidate.asType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( accessType == AccessType.PROPERTY && member.getKind() == ElementKind.METHOD ) {
|
else if ( accessType == AccessType.PROPERTY && candidate.getKind() == ElementKind.METHOD ) {
|
||||||
if ( !getterMatches(token, memberName) ) {
|
if ( !getterMatches(token, memberName) ) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final ExecutableElement method = (ExecutableElement) member;
|
final ExecutableElement method = (ExecutableElement) candidate;
|
||||||
type = method.getReturnType();
|
type = method.getReturnType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tokens.hasMoreTokens() ) {
|
if ( tokens.hasMoreTokens() ) {
|
||||||
final String nextToken = tokens.nextToken();
|
|
||||||
if ( type.getKind() == TypeKind.DECLARED ) {
|
if ( type.getKind() == TypeKind.DECLARED ) {
|
||||||
final DeclaredType declaredType = (DeclaredType) type;
|
final DeclaredType declaredType = (DeclaredType) type;
|
||||||
final TypeElement memberType = (TypeElement) declaredType.asElement();
|
final TypeElement memberType = (TypeElement) declaredType.asElement();
|
||||||
memberTypes.put( qualify(entityType.getQualifiedName().toString(), memberName.toString()),
|
memberTypes.put( qualify( entityType.getQualifiedName().toString(), memberName.toString() ),
|
||||||
memberType.getQualifiedName().toString() );
|
memberType.getQualifiedName().toString() );
|
||||||
final AccessType memberAccessType = getAccessType(memberType);
|
return memberMatchingParameter( memberType, param, tokens );
|
||||||
for ( Element entityMember : memberType.getEnclosedElements() ) {
|
|
||||||
if ( fieldMatchesParameter(memberType, param, entityMember, memberAccessType, tokens, nextToken) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final String memberType = memberType( member ).toString();
|
return candidate;
|
||||||
final String paramType = param.asType().toString();
|
|
||||||
if ( !isLegalAssignment( paramType, memberType ) ) {
|
|
||||||
context.message( param,
|
|
||||||
"matching field has type '" + memberType
|
|
||||||
+ "' in entity class '" + entityType + "'",
|
|
||||||
Diagnostic.Kind.ERROR );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,6 +1010,12 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Boolean> parameterNullability(ExecutableElement method, TypeElement entity) {
|
||||||
|
return method.getParameters().stream()
|
||||||
|
.map(param -> finderParameterNullable(entity, param))
|
||||||
|
.collect(toList());
|
||||||
|
}
|
||||||
|
|
||||||
private static List<String> parameterTypes(ExecutableElement method) {
|
private static List<String> parameterTypes(ExecutableElement method) {
|
||||||
return method.getParameters().stream()
|
return method.getParameters().stream()
|
||||||
.map(param -> param.asType().toString())
|
.map(param -> param.asType().toString())
|
||||||
|
@ -1008,6 +1028,39 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
||||||
.collect(toList());
|
.collect(toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isNullable(Element member) {
|
||||||
|
switch ( member.getKind() ) {
|
||||||
|
case METHOD:
|
||||||
|
final ExecutableElement method = (ExecutableElement) member;
|
||||||
|
if ( method.getReturnType().getKind().isPrimitive() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FIELD:
|
||||||
|
if ( member.asType().getKind().isPrimitive() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean nullable = true;
|
||||||
|
for ( AnnotationMirror mirror : member.getAnnotationMirrors() ) {
|
||||||
|
final TypeElement annotationType = (TypeElement) mirror.getAnnotationType().asElement();
|
||||||
|
final Name name = annotationType.getQualifiedName();
|
||||||
|
if ( name.contentEquals(Constants.ID) ) {
|
||||||
|
nullable = false;
|
||||||
|
}
|
||||||
|
if ( name.contentEquals("jakarta.validation.constraints.NotNull")) {
|
||||||
|
nullable = false;
|
||||||
|
}
|
||||||
|
if ( name.contentEquals(Constants.BASIC)
|
||||||
|
|| name.contentEquals(Constants.MANY_TO_ONE)
|
||||||
|
|| name.contentEquals(Constants.ONE_TO_ONE)) {
|
||||||
|
if ( FALSE.equals( getAnnotationValue(mirror, "optional") ) ) {
|
||||||
|
nullable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
|
||||||
private void checkParameters(
|
private void checkParameters(
|
||||||
ExecutableElement method,
|
ExecutableElement method,
|
||||||
List<String> paramNames, List<String> paramTypes,
|
List<String> paramNames, List<String> paramTypes,
|
||||||
|
|
|
@ -10,23 +10,24 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.hibernate.jpamodelgen.util.Constants;
|
import org.hibernate.jpamodelgen.util.Constants;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import static org.hibernate.jpamodelgen.util.TypeUtils.isPrimitive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class CriteriaFinderMethod extends AbstractFinderMethod {
|
public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
|
|
||||||
private final @Nullable String containerType;
|
private final @Nullable String containerType;
|
||||||
private final boolean isId;
|
private final List<Boolean> paramNullability;
|
||||||
|
|
||||||
public CriteriaFinderMethod(
|
public CriteriaFinderMethod(
|
||||||
AnnotationMetaEntity annotationMetaEntity,
|
AnnotationMetaEntity annotationMetaEntity,
|
||||||
String methodName, String entity,
|
String methodName, String entity,
|
||||||
@Nullable String containerType,
|
@Nullable String containerType,
|
||||||
List<String> paramNames, List<String> paramTypes,
|
List<String> paramNames, List<String> paramTypes,
|
||||||
boolean isId,
|
List<Boolean> paramNullability,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
String sessionName,
|
String sessionName,
|
||||||
|
@ -35,12 +36,12 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, 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.paramNullability = paramNullability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isId() {
|
public boolean isNullable(int index) {
|
||||||
return isId;
|
return paramNullability.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,11 +56,17 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
parameters( paramTypes, declaration );
|
parameters( paramTypes, declaration );
|
||||||
declaration
|
declaration
|
||||||
.append(" {");
|
.append(" {");
|
||||||
if ( isId ) {
|
for ( int i = 0; i< paramNames.size(); i++ ) {
|
||||||
declaration
|
final String paramName = paramNames.get(i);
|
||||||
.append("\n\tif (")
|
final String paramType = paramTypes.get(i);
|
||||||
.append(paramNames.get(0))
|
if ( !isNullable(i) && !isPrimitive(paramType) ) {
|
||||||
.append(" == null) throw new IllegalArgumentException(\"Null identifier\");");
|
declaration
|
||||||
|
.append("\n\tif (")
|
||||||
|
.append(paramName)
|
||||||
|
.append(" == null) throw new IllegalArgumentException(\"Null \" + ")
|
||||||
|
.append(paramName)
|
||||||
|
.append(");");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
.append("\n\tvar builder = ")
|
.append("\n\tvar builder = ")
|
||||||
|
@ -89,7 +96,7 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
}
|
}
|
||||||
declaration
|
declaration
|
||||||
.append("\n\t\t\t");
|
.append("\n\t\t\t");
|
||||||
if ( !isId && !isPrimitive(paramType) ) { //TODO: check the entity to see if it's @Basic(optional=false)
|
if ( isNullable(i) && !isPrimitive(paramType) ) {
|
||||||
declaration
|
declaration
|
||||||
.append(paramName)
|
.append(paramName)
|
||||||
.append("==null")
|
.append("==null")
|
||||||
|
@ -162,13 +169,6 @@ public class CriteriaFinderMethod extends AbstractFinderMethod {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPrimitive(String paramType) {
|
|
||||||
return PRIMITIVE_TYPES.contains( paramType );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Set<String> PRIMITIVE_TYPES =
|
|
||||||
Set.of("boolean", "char", "long", "int", "short", "byte", "double", "float");
|
|
||||||
|
|
||||||
private StringBuilder returnType() {
|
private StringBuilder returnType() {
|
||||||
StringBuilder type = new StringBuilder();
|
StringBuilder type = new StringBuilder();
|
||||||
boolean returnsUni = isReactive()
|
boolean returnsUni = isReactive()
|
||||||
|
|
|
@ -39,8 +39,8 @@ public class IdFinderMethod extends AbstractFinderMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isId() {
|
boolean isNullable(int index) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -13,10 +13,13 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class NaturalIdFinderMethod extends AbstractFinderMethod {
|
public class NaturalIdFinderMethod extends AbstractFinderMethod {
|
||||||
|
|
||||||
|
private final List<Boolean> paramNullability;
|
||||||
|
|
||||||
public NaturalIdFinderMethod(
|
public NaturalIdFinderMethod(
|
||||||
AnnotationMetaEntity annotationMetaEntity,
|
AnnotationMetaEntity annotationMetaEntity,
|
||||||
String methodName, String entity,
|
String methodName, String entity,
|
||||||
List<String> paramNames, List<String> paramTypes,
|
List<String> paramNames, List<String> paramTypes,
|
||||||
|
List<Boolean> paramNullability,
|
||||||
boolean belongsToDao,
|
boolean belongsToDao,
|
||||||
String sessionType,
|
String sessionType,
|
||||||
String sessionName,
|
String sessionName,
|
||||||
|
@ -24,12 +27,13 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
|
||||||
boolean addNonnullAnnotation) {
|
boolean addNonnullAnnotation) {
|
||||||
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
|
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
|
||||||
paramNames, paramTypes, addNonnullAnnotation );
|
paramNames, paramTypes, addNonnullAnnotation );
|
||||||
|
this.paramNullability = paramNullability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isId() {
|
boolean isNullable(int index) {
|
||||||
// natural ids can be null
|
// natural ids can be null
|
||||||
return false;
|
return paramNullability.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -63,8 +63,8 @@ public class QueryMethod extends AbstractQueryMethod {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean isId() {
|
boolean isNullable(int index) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -493,4 +493,11 @@ public final class TypeUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isPrimitive(String paramType) {
|
||||||
|
return PRIMITIVE_TYPES.contains( paramType );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Set<String> PRIMITIVE_TYPES =
|
||||||
|
Set.of("boolean", "char", "long", "int", "short", "byte", "double", "float");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue