Skip to content

Commit a933133

Browse files
committed
Handle generic return type in Spring Data JPA repositories
Fixes: #31774
1 parent 0f2d39a commit a933133

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

extensions/spring-data-jpa/deployment/src/main/java/io/quarkus/spring/data/deployment/generate/DerivedMethodsAdder.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
import org.jboss.jandex.IndexView;
2121
import org.jboss.jandex.MethodInfo;
2222
import org.jboss.jandex.Type;
23+
import org.jboss.jandex.TypeVariable;
2324
import org.springframework.data.domain.Pageable;
2425
import org.springframework.data.domain.Sort;
2526

2627
import io.quarkus.deployment.bean.JavaBeanUtil;
28+
import io.quarkus.deployment.util.JandexUtil;
2729
import io.quarkus.gizmo.ClassCreator;
2830
import io.quarkus.gizmo.ClassOutput;
2931
import io.quarkus.gizmo.FieldDescriptor;
@@ -169,7 +171,8 @@ public void add(ClassCreator classCreator, FieldDescriptor entityClassFieldDescr
169171
methodCreator.readInstanceField(entityClassFieldDescriptor, methodCreator.getThis()),
170172
methodCreator.load(finalQuery), sort, paramsArray);
171173

172-
Type resultType = verifyQueryResultType(method.returnType(), index);
174+
Type resultType = extractResultType(repositoryClassInfo, method);
175+
173176
DotName customResultTypeName = resultType.name();
174177

175178
if (customResultTypeName.equals(entityClassInfo.name())
@@ -287,6 +290,25 @@ public void add(ClassCreator classCreator, FieldDescriptor entityClassFieldDescr
287290
}
288291
}
289292

293+
private Type extractResultType(ClassInfo repositoryClassInfo, MethodInfo method) {
294+
Type resultType = verifyQueryResultType(method.returnType(), index);
295+
if (resultType.kind() == Type.Kind.TYPE_VARIABLE) {
296+
// we can handle the generic result type case where interface only declares one generic type that is the same as the method result type uses (TODO: look into enhancing)
297+
// this is accomplished by resolving the generic type from the interface we are actually implementing
298+
TypeVariable resultTypeVariable = resultType.asTypeVariable();
299+
List<TypeVariable> interfaceTypeVariables = method.declaringClass().typeParameters();
300+
if (interfaceTypeVariables.size() == 1 && interfaceTypeVariables.get(0)
301+
.equals(resultTypeVariable)) {
302+
List<Type> resolveTypeParameters = JandexUtil.resolveTypeParameters(repositoryClassInfo.name(),
303+
method.declaringClass().name(), index);
304+
if (resolveTypeParameters.size() == 1) {
305+
return resolveTypeParameters.get(0);
306+
}
307+
}
308+
}
309+
return resultType;
310+
}
311+
290312
private void addAllMethodOfIntermediateRepository(DotName interfaceDotName, Set<MethodInfo> result) {
291313
if (GenerationUtil.isIntermediateRepository(interfaceDotName, index)) {
292314
ClassInfo classInfo = index.getClassByName(interfaceDotName);

integration-tests/spring-data-jpa/src/main/java/io/quarkus/it/spring/data/jpa/IntermediatePostRepository.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
import java.time.ZonedDateTime;
44
import java.util.List;
55

6+
import org.springframework.data.repository.NoRepositoryBean;
7+
68
/**
79
* Used to ensure that entity relationships work correctly
810
*/
9-
public interface IntermediatePostRepository extends BypassHolderRepository<Post, Long> {
11+
@NoRepositoryBean
12+
public interface IntermediatePostRepository<T extends ByPassHolder> extends BypassHolderRepository<T, Long> {
1013

11-
List<Post> findByPostedBefore(ZonedDateTime zdt);
14+
List<T> findByPostedBefore(ZonedDateTime zdt);
1215
}

integration-tests/spring-data-jpa/src/main/java/io/quarkus/it/spring/data/jpa/PostRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/**
66
* Used to ensure that entity relationships work correctly
77
*/
8-
public interface PostRepository extends IntermediatePostRepository {
8+
public interface PostRepository extends IntermediatePostRepository<Post> {
99

1010
List<Post> findAllByOrganization(String organization);
1111

0 commit comments

Comments
 (0)