Skip to content

Commit 646d13d

Browse files
committed
Support multiple levels of repository interfaces in Spring Data JPA
Closes: #31570
1 parent 3bf5153 commit 646d13d

File tree

6 files changed

+37
-13
lines changed

6 files changed

+37
-13
lines changed

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
import java.lang.reflect.Modifier;
77
import java.util.ArrayList;
88
import java.util.HashMap;
9+
import java.util.LinkedHashSet;
910
import java.util.List;
1011
import java.util.Map;
12+
import java.util.Set;
1113
import java.util.function.Consumer;
1214

1315
import jakarta.transaction.Transactional;
@@ -56,18 +58,15 @@ public DerivedMethodsAdder(IndexView index, TypeBundle typeBundle, ClassOutput n
5658
public void add(ClassCreator classCreator, FieldDescriptor entityClassFieldDescriptor,
5759
String generatedClassName, ClassInfo repositoryClassInfo, ClassInfo entityClassInfo) {
5860
MethodNameParser methodNameParser = new MethodNameParser(entityClassInfo, index);
59-
List<MethodInfo> repoMethods = new ArrayList<>(repositoryClassInfo.methods());
61+
LinkedHashSet<MethodInfo> repoMethods = new LinkedHashSet<>(repositoryClassInfo.methods());
6062

6163
// Remember custom return type methods: {resultType:[methodName]}
6264
Map<DotName, List<String>> customResultTypes = new HashMap<>(3);
6365
Map<DotName, DotName> customResultTypeImplNames = new HashMap<>(3);
6466

6567
//As intermediate interfaces are supported for spring data repositories, we need to search the methods declared in such interfaced and add them to the methods to implement list
6668
for (DotName extendedInterface : repositoryClassInfo.interfaceNames()) {
67-
if (GenerationUtil.isIntermediateRepository(extendedInterface, index)) {
68-
List<MethodInfo> methods = index.getClassByName(extendedInterface).methods();
69-
repoMethods.addAll(methods);
70-
}
69+
addAllMethodOfIntermediateRepository(extendedInterface, repoMethods);
7170
}
7271
for (MethodInfo method : repoMethods) {
7372
if (method.annotation(DotNames.SPRING_DATA_QUERY) != null) { // handled by CustomQueryMethodsAdder
@@ -288,6 +287,17 @@ public void add(ClassCreator classCreator, FieldDescriptor entityClassFieldDescr
288287
}
289288
}
290289

290+
private void addAllMethodOfIntermediateRepository(DotName interfaceDotName, Set<MethodInfo> result) {
291+
if (GenerationUtil.isIntermediateRepository(interfaceDotName, index)) {
292+
ClassInfo classInfo = index.getClassByName(interfaceDotName);
293+
List<MethodInfo> methods = classInfo.methods();
294+
result.addAll(methods);
295+
for (DotName superInterface : classInfo.interfaceNames()) {
296+
addAllMethodOfIntermediateRepository(superInterface, result);
297+
}
298+
}
299+
}
300+
291301
private void generateCustomResultTypes(DotName interfaceName, DotName implName, ClassInfo entityClassInfo,
292302
List<String> queryMethods) {
293303

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.quarkus.it.spring.data.jpa;
2+
3+
public interface ByPassHolder {
4+
5+
boolean isBypass();
6+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import org.springframework.data.repository.NoRepositoryBean;
77

88
@NoRepositoryBean
9-
public interface IntermediateRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
9+
public interface BypassHolderRepository<T extends ByPassHolder, ID extends Serializable> extends JpaRepository<T, ID> {
1010

1111
default public void doNothing() {
1212
}
@@ -15,4 +15,5 @@ default public T findMandatoryById(ID id) {
1515
return findById(id).orElseThrow(() -> new IllegalStateException("not found: " + id));
1616
}
1717

18+
Post findFirstByBypassTrue();
1819
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.quarkus.it.spring.data.jpa;
2+
3+
import java.time.ZonedDateTime;
4+
import java.util.List;
5+
6+
/**
7+
* Used to ensure that entity relationships work correctly
8+
*/
9+
public interface IntermediatePostRepository extends BypassHolderRepository<Post, Long> {
10+
11+
List<Post> findByPostedBefore(ZonedDateTime zdt);
12+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
@Entity(name = "Post")
2020
@Table(name = "post")
21-
public class Post {
21+
public class Post implements ByPassHolder {
2222

2323
@Id
2424
@SequenceGenerator(name = "postSeqGen", sequenceName = "postSeq", initialValue = 100, allocationSize = 1)

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
package io.quarkus.it.spring.data.jpa;
22

3-
import java.time.ZonedDateTime;
43
import java.util.List;
54

65
/**
76
* Used to ensure that entity relationships work correctly
87
*/
9-
public interface PostRepository extends IntermediateRepository<Post, Long> {
10-
11-
Post findFirstByBypassTrue();
12-
13-
List<Post> findByPostedBefore(ZonedDateTime zdt);
8+
public interface PostRepository extends IntermediatePostRepository {
149

1510
List<Post> findAllByOrganization(String organization);
1611

0 commit comments

Comments
 (0)