better impl of repository id lookup methods returning Optional

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-04-11 22:18:14 +02:00
parent f27dc7d3a8
commit f6b366fa41
10 changed files with 81 additions and 31 deletions

View File

@ -74,6 +74,9 @@ public interface BookAuthorRepository {
@Find
Book byTitleAndDate(String title, LocalDate publicationDate);
@Find
Optional<Book> maybeByTitleAndDate(String title, LocalDate publicationDate);
@Find
Book bookById(@By("isbn") String id);

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.processor.annotation;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import java.util.StringTokenizer;
@ -24,6 +26,7 @@ public abstract class AbstractCriteriaMethod extends AbstractFinderMethod {
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity,
@Nullable String containerType,
boolean belongsToDao,
String sessionType, String sessionName,
List<String> fetchProfiles,
@ -35,8 +38,9 @@ public abstract class AbstractCriteriaMethod extends AbstractFinderMethod {
List<Boolean> multivalued,
List<Boolean> paramPatterns,
String fullReturnType) {
super(annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, orderBys, addNonnullAnnotation, convertToDataExceptions, fullReturnType);
super(annotationMetaEntity, method, methodName, entity, containerType, belongsToDao, sessionType, sessionName,
fetchProfiles, paramNames, paramTypes, orderBys, addNonnullAnnotation, convertToDataExceptions,
fullReturnType);
this.multivalued = multivalued;
this.paramPatterns = paramPatterns;
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.processor.annotation;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.internal.util.StringHelper;
import javax.lang.model.element.ExecutableElement;
@ -19,6 +20,7 @@ import static org.hibernate.processor.util.StringUtil.getUpperUnderscoreCaseFrom
* @author Gavin King
*/
public abstract class AbstractFinderMethod extends AbstractQueryMethod {
final @Nullable String containerType;
final String entity;
final List<String> fetchProfiles;
@ -27,6 +29,7 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
ExecutableElement method,
String methodName,
String entity,
@Nullable String containerType,
boolean belongsToDao,
String sessionType,
String sessionName,
@ -46,6 +49,7 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
convertToDataExceptions,
fullReturnType );
this.entity = entity;
this.containerType = containerType;
this.fetchProfiles = fetchProfiles;
}

View File

@ -1482,9 +1482,9 @@ public class AnnotationMetaEntity extends AnnotationMeta {
Diagnostic.Kind.ERROR );
}
else {
if ( containerType != null ) {
if ( containerType != null
&& !containerType.getQualifiedName().contentEquals(OPTIONAL) ) {
// multiple results, so it has to be a criteria finder
// or, alternatively, Optional, which for now we treat similarly
createCriteriaFinder( method, declaredType, containerType.toString(), entity );
}
else {
@ -1497,6 +1497,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
message( parameter, "ordering would have no effect", Diagnostic.Kind.ERROR);
}
}
final String containerTypeName = containerType==null ? null : OPTIONAL;
final long parameterCount =
method.getParameters().stream()
.filter(AnnotationMetaEntity::isFinderParameterMappingToAttribute)
@ -1506,10 +1507,10 @@ public class AnnotationMetaEntity extends AnnotationMeta {
message( method, "missing parameter", Diagnostic.Kind.ERROR );
break;
case 1:
createSingleParameterFinder( method, declaredType, entity );
createSingleParameterFinder( method, declaredType, entity, containerTypeName );
break;
default:
createMultipleParameterFinder( method, declaredType, entity );
createMultipleParameterFinder( method, declaredType, entity, containerTypeName );
}
}
}
@ -1771,7 +1772,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
}
}
private void createMultipleParameterFinder(ExecutableElement method, TypeMirror returnType, TypeElement entity) {
private void createMultipleParameterFinder(
ExecutableElement method, TypeMirror returnType, TypeElement entity, @Nullable String containerType) {
final String methodName = method.getSimpleName().toString();
final List<String> paramNames = parameterNames( method, entity );
final List<String> paramTypes = parameterTypes( method );
@ -1796,6 +1798,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
this, method,
methodName,
returnType.toString(),
containerType,
paramNames,
paramTypes,
parameterNullability(method, entity),
@ -1816,7 +1819,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
this, method,
methodName,
returnType.toString(),
null,
containerType,
paramNames,
paramTypes,
parameterNullability(method, entity),
@ -1835,7 +1838,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
}
}
private void createSingleParameterFinder(ExecutableElement method, TypeMirror returnType, TypeElement entity) {
private void createSingleParameterFinder(
ExecutableElement method, TypeMirror returnType, TypeElement entity, @Nullable String containerType) {
final String methodName = method.getSimpleName().toString();
final VariableElement parameter =
method.getParameters().stream()
@ -1855,6 +1859,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
this, method,
methodName,
returnType.toString(),
containerType,
paramNames,
paramTypes,
repository,
@ -1873,6 +1878,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
this, method,
methodName,
returnType.toString(),
containerType,
paramNames,
paramTypes,
parameterNullability(method, entity),
@ -1894,7 +1900,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
this, method,
methodName,
returnType.toString(),
null,
containerType,
paramNames,
paramTypes,
parameterNullability(method, entity),

View File

@ -33,9 +33,9 @@ public class CriteriaDeleteMethod extends AbstractCriteriaMethod {
boolean addNonnullAnnotation,
boolean dataRepository,
String fullReturnType) {
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, emptyList(),
paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository, multivalued, paramPatterns,
fullReturnType);
super( annotationMetaEntity, method, methodName, entity, null, belongsToDao, sessionType,
sessionName, emptyList(), paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository,
multivalued, paramPatterns, fullReturnType);
this.paramNullability = paramNullability;
}

View File

@ -16,7 +16,6 @@ import java.util.List;
*/
public class CriteriaFinderMethod extends AbstractCriteriaMethod {
private final @Nullable String containerType;
private final List<Boolean> paramNullability;
CriteriaFinderMethod(
@ -36,10 +35,9 @@ public class CriteriaFinderMethod extends AbstractCriteriaMethod {
boolean addNonnullAnnotation,
boolean dataRepository,
String fullReturnType) {
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, orderBys, addNonnullAnnotation, dataRepository, multivalued, paramPatterns,
fullReturnType);
this.containerType = containerType;
super( annotationMetaEntity, method, methodName, entity, containerType, belongsToDao, sessionType, sessionName,
fetchProfiles, paramNames, paramTypes, orderBys, addNonnullAnnotation, dataRepository, multivalued,
paramPatterns, fullReturnType);
this.paramNullability = paramNullability;
}

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.processor.annotation;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
@ -24,6 +26,7 @@ public class IdFinderMethod extends AbstractFinderMethod {
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity,
@Nullable String containerType, //must be null or Optional
List<String> paramNames, List<String> paramTypes,
boolean belongsToDao,
String sessionType,
@ -32,8 +35,8 @@ public class IdFinderMethod extends AbstractFinderMethod {
boolean addNonnullAnnotation,
boolean dataRepository,
String fullReturnType) {
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository, fullReturnType );
super( annotationMetaEntity, method, methodName, entity, containerType, belongsToDao, sessionType, sessionName,
fetchProfiles, paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository, fullReturnType );
int idParameter = idParameter(paramNames, paramTypes);
this.paramName = paramNames.get(idParameter);
this.paramType = paramTypes.get(idParameter);
@ -81,7 +84,9 @@ public class IdFinderMethod extends AbstractFinderMethod {
}
private void throwIfNull(StringBuilder declaration) {
if ( isUsingStatelessSession() ) {
if ( containerType == null ) {
declaration
.append(";\n");
if (dataRepository) {
declaration
.append("\t\tif (_result == null) throw new ")
@ -111,20 +116,26 @@ public class IdFinderMethod extends AbstractFinderMethod {
.append("\treturn _result;\n");
}
}
else {
declaration
.append(");\n");
}
}
private void varOrReturn(StringBuilder declaration) {
if (dataRepository) {
declaration
.append("\ttry {\n");
.append("\ttry {\n\t");
}
if ( isUsingStatelessSession() ) {
if ( containerType == null ) {
declaration
.append("\t\tvar _result = ");
.append("\tvar _result = ");
}
else {
declaration
.append("\t\treturn ");
.append("\treturn ")
.append(annotationMetaEntity.staticImport(containerType, "ofNullable"))
.append('(');
}
declaration
.append(sessionName);
@ -140,7 +151,7 @@ public class IdFinderMethod extends AbstractFinderMethod {
declaration
.append("\t\t\t.load(")
.append(paramName)
.append(");\n");
.append(")");
}
private void findWithNoFetchProfiles(StringBuilder declaration) {
@ -161,7 +172,7 @@ public class IdFinderMethod extends AbstractFinderMethod {
.append(')');
}
declaration
.append(");\n");
.append(")");
}
private static void nullCheck(StringBuilder declaration, String parameterName) {

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.processor.annotation;
import org.checkerframework.checker.nullness.qual.Nullable;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
@ -22,6 +24,7 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity,
@Nullable String containerType, //must be null or Optional
List<String> paramNames, List<String> paramTypes,
List<Boolean> paramNullability,
boolean belongsToDao,
@ -31,8 +34,8 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
boolean addNonnullAnnotation,
boolean dataRepository,
String fullReturnType) {
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository, fullReturnType );
super( annotationMetaEntity, method, methodName, entity, containerType, belongsToDao, sessionType, sessionName,
fetchProfiles, paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository, fullReturnType );
this.paramNullability = paramNullability;
}
@ -85,8 +88,15 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
.append(")\n");
}
}
declaration
.append("\t\t\t.load();\n");
if ( containerType == null ) {
//TODO we should probably throw if this returns null
declaration
.append("\t\t\t.load();\n");
}
else {
declaration
.append("\t\t\t.loadOptional();\n");
}
}
private void findReactively(StringBuilder declaration) {

View File

@ -8,6 +8,7 @@ import org.hibernate.annotations.processing.SQL;
import org.hibernate.query.SelectionQuery;
import java.util.List;
import java.util.Optional;
public interface StatefulDao {
@ -16,12 +17,18 @@ public interface StatefulDao {
@Find
Book getBook(String isbn);
@Find
Optional<Book> getBookMaybe(String isbn);
@Find(enabledFetchProfiles="Goodbye")
Book getBookFetching(String isbn);
@Find
Book getBook(String title, String author);
@Find
Optional<Book> getBookMaybe(String title, String author);
@Find(enabledFetchProfiles="Hello")
Book getBookFetching(String title, String author);

View File

@ -8,6 +8,7 @@ import org.hibernate.annotations.processing.SQL;
import org.hibernate.query.SelectionQuery;
import java.util.List;
import java.util.Optional;
public interface StatelessDao {
@ -16,12 +17,18 @@ public interface StatelessDao {
@Find
Book getBook(String isbn);
@Find
Optional<Book> getBookMaybe(String isbn);
@Find(enabledFetchProfiles="Goodbye")
Book getBookFetching(String isbn);
@Find
Book getBook(String title, String author);
@Find
Optional<Book> getBookMaybe(String title, String author);
@Find(enabledFetchProfiles="Hello")
Book getBookFetching(String title, String author);