HHH-17891 support method-level interceptors for JD repositories

as required by the spec

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-03-26 20:33:49 +01:00
parent c08b8f8c38
commit ccf5fcc5b2
14 changed files with 86 additions and 21 deletions

View File

@ -3,11 +3,13 @@ package org.hibernate.processor.test.data.eg;
import jakarta.data.repository.CrudRepository;
import jakarta.data.repository.Find;
import jakarta.data.repository.Repository;
import jakarta.transaction.Transactional;
import java.util.List;
@Repository
public interface Bookshop extends CrudRepository<Book,String> {
@Find
@Transactional
List<Book> byPublisher(String publisher_name);
}

View File

@ -104,7 +104,16 @@ public final class ClassWriter {
for ( MetaAttribute metaMember : members ) {
if ( metaMember.hasTypedAttribute() ) {
metaMember.getAttributeDeclarationString().lines()
.forEach(line -> pw.println('\t' + line));
.forEach(line -> {
pw.println('\t' + line);
if ( line.trim().startsWith("@Override") ) {
metaMember.inheritedAnnotations()
.forEach(x -> {
pw.print('\t');
pw.println(x);
});
}
});
}
}
pw.println();

View File

@ -9,10 +9,17 @@ package org.hibernate.processor.annotation;
import org.hibernate.processor.model.MetaAttribute;
import org.hibernate.processor.model.Metamodel;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;
import static org.hibernate.processor.annotation.AnnotationMetaEntity.usingReactiveSession;
import static org.hibernate.processor.annotation.AnnotationMetaEntity.usingReactiveSessionAccess;
import static org.hibernate.processor.annotation.AnnotationMetaEntity.usingStatelessSession;
import static org.hibernate.processor.util.Constants.ENTITY_MANAGER;
import static org.hibernate.processor.util.TypeUtils.hasAnnotation;
/**
* @author Gavin King
@ -20,11 +27,16 @@ import static org.hibernate.processor.util.Constants.ENTITY_MANAGER;
public abstract class AbstractAnnotatedMethod implements MetaAttribute {
final AnnotationMetaEntity annotationMetaEntity;
private final ExecutableElement method;
final String sessionType;
final String sessionName;
public AbstractAnnotatedMethod(AnnotationMetaEntity annotationMetaEntity, String sessionName, String sessionType) {
public AbstractAnnotatedMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String sessionName, String sessionType) {
this.annotationMetaEntity = annotationMetaEntity;
this.method = method;
this.sessionName = sessionName;
this.sessionType = sessionType;
}
@ -54,5 +66,16 @@ public abstract class AbstractAnnotatedMethod implements MetaAttribute {
return isReactiveSessionAccess() ? "_session" : sessionName;
}
@Override
public List<AnnotationMirror> inheritedAnnotations() {
if ( annotationMetaEntity.isJakartaDataRepository() ) {
return method.getAnnotationMirrors().stream()
.filter(annotationMirror -> hasAnnotation(annotationMirror.getAnnotationType().asElement(),
"jakarta.interceptor.InterceptorBinding"))
.collect(toList());
}
else {
return emptyList();
}
}
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.processor.annotation;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import java.util.StringTokenizer;
@ -21,6 +22,7 @@ public abstract class AbstractCriteriaMethod extends AbstractFinderMethod {
public AbstractCriteriaMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity,
boolean belongsToDao,
String sessionType, String sessionName,
@ -32,7 +34,7 @@ public abstract class AbstractCriteriaMethod extends AbstractFinderMethod {
boolean convertToDataExceptions,
List<Boolean> multivalued,
List<Boolean> paramPatterns) {
super(annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
super(annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, orderBys, addNonnullAnnotation, convertToDataExceptions);
this.multivalued = multivalued;
this.paramPatterns = paramPatterns;

View File

@ -8,6 +8,7 @@ package org.hibernate.processor.annotation;
import org.hibernate.internal.util.StringHelper;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import java.util.Locale;
@ -24,6 +25,7 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
AbstractFinderMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName,
String entity,
boolean belongsToDao,
@ -35,7 +37,7 @@ public abstract class AbstractFinderMethod extends AbstractQueryMethod {
List<OrderBy> orderBys,
boolean addNonnullAnnotation,
boolean convertToDataExceptions) {
super( annotationMetaEntity,
super( annotationMetaEntity, method,
methodName,
paramNames, paramTypes, entity,
sessionType, sessionName,

View File

@ -9,6 +9,7 @@ package org.hibernate.processor.annotation;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.AssertionFailure;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@ -51,6 +52,7 @@ public abstract class AbstractQueryMethod extends AbstractAnnotatedMethod {
AbstractQueryMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName,
List<String> paramNames, List<String> paramTypes,
@Nullable String returnTypeName,
@ -60,7 +62,7 @@ public abstract class AbstractQueryMethod extends AbstractAnnotatedMethod {
List<OrderBy> orderBys,
boolean addNonnullAnnotation,
boolean dataRepository) {
super(annotationMetaEntity, sessionName, sessionType);
super(annotationMetaEntity, method, sessionName, sessionType);
this.methodName = methodName;
this.paramNames = paramNames;
this.paramTypes = paramTypes;

View File

@ -304,6 +304,10 @@ public class AnnotationMetaEntity extends AnnotationMeta {
return repository;
}
boolean isJakartaDataRepository() {
return jakartaDataRepository;
}
@Override
String getSessionType() {
return sessionType;
@ -1206,7 +1210,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
putMember(
methodName + '.' + entity,
new LifecycleMethod(
this,
this, method,
entity,
methodName,
parameter.getSimpleName().toString(),
@ -1414,7 +1418,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
}
putMember( methodKey,
new CriteriaFinderMethod(
this,
this, method,
methodName,
returnType.toString(),
containerType,
@ -1458,7 +1462,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
}
putMember( methodKey,
new CriteriaDeleteMethod(
this,
this, method,
methodName,
entity.getQualifiedName().toString(),
returnType.toString(),
@ -1652,7 +1656,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
&& matchesNaturalKey( entity, fieldTypes ) ) {
putMember( methodKey,
new NaturalIdFinderMethod(
this,
this, method,
methodName,
returnType.toString(),
paramNames,
@ -1671,7 +1675,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
final List<Boolean> paramPatterns = parameterPatterns( method );
putMember( methodKey,
new CriteriaFinderMethod(
this,
this, method,
methodName,
returnType.toString(),
null,
@ -1709,7 +1713,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
case ID:
putMember( methodKey,
new IdFinderMethod(
this,
this, method,
methodName,
returnType.toString(),
paramNames,
@ -1726,7 +1730,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
case NATURAL_ID:
putMember( methodKey,
new NaturalIdFinderMethod(
this,
this, method,
methodName,
returnType.toString(),
paramNames,
@ -1746,7 +1750,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
final List<Boolean> paramPatterns = parameterPatterns( method );
putMember( methodKey,
new CriteriaFinderMethod(
this,
this, method,
methodName,
returnType.toString(),
null,
@ -2092,7 +2096,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
final QueryMethod attribute =
new QueryMethod(
this,
this, method,
method.getSimpleName().toString(),
queryString,
returnType == null ? null : returnType.toString(),

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.processor.annotation;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import static java.util.Collections.emptyList;
@ -20,6 +21,7 @@ public class CriteriaDeleteMethod extends AbstractCriteriaMethod {
CriteriaDeleteMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity, String returnType,
List<String> paramNames,
List<String> paramTypes,
@ -31,7 +33,7 @@ public class CriteriaDeleteMethod extends AbstractCriteriaMethod {
String sessionName,
boolean addNonnullAnnotation,
boolean dataRepository) {
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, emptyList(),
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, emptyList(),
paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository, multivalued, paramPatterns );
this.paramNullability = paramNullability;
this.returnType = returnType;

View File

@ -10,6 +10,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.AssertionFailure;
import org.hibernate.processor.util.Constants;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
/**
@ -22,6 +23,7 @@ public class CriteriaFinderMethod extends AbstractCriteriaMethod {
CriteriaFinderMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity,
@Nullable String containerType,
List<String> paramNames, List<String> paramTypes,
@ -35,7 +37,7 @@ public class CriteriaFinderMethod extends AbstractCriteriaMethod {
List<OrderBy> orderBys,
boolean addNonnullAnnotation,
boolean dataRepository) {
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, orderBys, addNonnullAnnotation, dataRepository, multivalued, paramPatterns );
this.containerType = containerType;
this.paramNullability = paramNullability;

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.processor.annotation;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import static java.util.Collections.emptyList;
@ -21,6 +22,7 @@ public class IdFinderMethod extends AbstractFinderMethod {
public IdFinderMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity,
List<String> paramNames, List<String> paramTypes,
boolean belongsToDao,
@ -29,7 +31,7 @@ public class IdFinderMethod extends AbstractFinderMethod {
List<String> fetchProfiles,
boolean addNonnullAnnotation,
boolean dataRepository) {
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository );
int idParameter = idParameter(paramNames, paramTypes);
this.paramName = paramNames.get(idParameter);

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.processor.annotation;
import javax.lang.model.element.ExecutableElement;
import static org.hibernate.processor.util.Constants.UNI;
public class LifecycleMethod extends AbstractAnnotatedMethod {
@ -19,6 +21,7 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
public LifecycleMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String entity,
String methodName,
String parameterName,
@ -28,7 +31,7 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
boolean addNonnullAnnotation,
boolean iterateParameter,
boolean returnArgument) {
super(annotationMetaEntity, sessionName, sessionType);
super(annotationMetaEntity, method, sessionName, sessionType);
this.entity = entity;
this.methodName = methodName;
this.parameterName = parameterName;

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.processor.annotation;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import static java.util.Collections.emptyList;
@ -19,6 +20,7 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
public NaturalIdFinderMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName, String entity,
List<String> paramNames, List<String> paramTypes,
List<Boolean> paramNullability,
@ -28,7 +30,7 @@ public class NaturalIdFinderMethod extends AbstractFinderMethod {
List<String> fetchProfiles,
boolean addNonnullAnnotation,
boolean dataRepository) {
super( annotationMetaEntity, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
super( annotationMetaEntity, method, methodName, entity, belongsToDao, sessionType, sessionName, fetchProfiles,
paramNames, paramTypes, emptyList(), addNonnullAnnotation, dataRepository );
this.paramNullability = paramNullability;
}

View File

@ -10,6 +10,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.hibernate.AssertionFailure;
import org.hibernate.internal.util.StringHelper;
import javax.lang.model.element.ExecutableElement;
import java.util.List;
import static org.hibernate.processor.util.Constants.QUERY;
@ -28,6 +29,7 @@ public class QueryMethod extends AbstractQueryMethod {
QueryMethod(
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String methodName,
String queryString,
@Nullable
@ -44,7 +46,7 @@ public class QueryMethod extends AbstractQueryMethod {
List<OrderBy> orderBys,
boolean addNonnullAnnotation,
boolean dataRepository) {
super( annotationMetaEntity,
super( annotationMetaEntity, method,
methodName,
paramNames, paramTypes, returnTypeName,
sessionType, sessionName,

View File

@ -6,6 +6,11 @@
*/
package org.hibernate.processor.model;
import javax.lang.model.element.AnnotationMirror;
import java.util.List;
import static java.util.Collections.emptyList;
/**
* @author Hardy Ferentschik
*/
@ -27,4 +32,7 @@ public interface MetaAttribute {
Metamodel getHostingEntity();
default List<AnnotationMirror> inheritedAnnotations() {
return emptyList();
}
}