如何停止Spring Data JPA自动查询生成?

Nic*_*ote 6 spring jpa spring-data spring-data-jpa

我已在 Spring Data JpaRespository 上添加了一个具有单个自定义方法的自定义接口,如该问题的答案中所述;

如何向 Spring Data JPA 添加自定义方法

但是现在我收到以下错误;

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property customMethod found for type Account!
    at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
    at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
Run Code Online (Sandbox Code Playgroud)

这似乎是因为 Spring Data 试图生成“customMethod”的查询,认为它是“Account”的属性。

如何停止给定方法的自动查询生成?!

更新我的代码具体如下;

public interface CacheInvalidatingRepo<T> {
    public void invalidateCache(T obj);
}

@Component
public class CacheInvalidatingRepoImpl<T> implements CacheInvalidatingRepo<T> {

    @Override
    public void invalidateCache(T obj) {
        // kill the entity manager cache
    }

}

public interface VerificationRepo extends JpaRepository<Verification, BigInteger>, JpaSpecificationExecutor<Verification>, CacheInvalidatingRepo<Verification> {

}
Run Code Online (Sandbox Code Playgroud)

结果如下;

Caused by: org.springframework.data.mapping.PropertyReferenceException: No property invalidateCachefound for type Verification!
    at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
    at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
    at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:241)
    at org.springframework.data.repository.query.parser.Part.<init>(Part.java:76)
Run Code Online (Sandbox Code Playgroud)

小智 1

长话短说

我也遇到了类似的问题,我花了很长时间才找到答案。就我而言,事实证明我的 Impl 类位于不同的包中。例如

Repository Interface.      : com.example.dao.repo.api.MyRepository
Custom Interface           : com.example.dao.repo.api.MyRepositoryCustom
Custom Implementation Class: com.example.dao.repo.impl.MyRepositoryCustomImpl
Run Code Online (Sandbox Code Playgroud)

那行不通。通过将 impl 类移至接口包下方解决了这个问题。

Repository Interface.      : com.example.dao.repo.MyRepository
Custom Interface           : com.example.dao.repo.MyRepositoryCustom
Custom Implementation Class: com.example.dao.repo.impl.MyRepositoryCustomImpl
Run Code Online (Sandbox Code Playgroud)

分析

Spring Data 创建存储库的方式似乎是它会尝试检测是否存在任何所谓的片段(自定义实现)。如果它可以检测到自定义接口但不能检测到 Impl 类(无论是由于命名约定还是包位置),Spring 将回退到生成方法的其他方法,这会导致误导性消息“No property xxx for xxx”。

Spring Data 文档实际上对此做了一些说明,但它很微妙并且很容易被忽略:

存储库基础结构尝试通过扫描在其中找到存储库的包下面的类来自动检测自定义实现片段。这些类需要遵循附加后缀(默认为 Impl)的命名约定。

如果您打开 spring 数据的调试级别日志并且您的片段类已加载,您应该能够看到如下所示的日志。否则可能意味着 Spring 无法加载该片段。(尝试使用 SpringBoot 2.7)

DEBUG [main] org.springframework.data.repository.config.RepositoryBeanDefinitionBuilder [RepositoryBeanDefinitionBuilder.java:196] Registering repository fragment implementation: myRepositoryCustomImpl com.example.dao.repo.impl.MyRepositoryCustomImpl
DEBUG [main] org.springframework.data.repository.config.RepositoryBeanDefinitionBuilder [RepositoryBeanDefinitionBuilder.java:218] Registering repository fragment: myRepositoryCustomImplFragment
Run Code Online (Sandbox Code Playgroud)

聚苯乙烯

我知道这是一个非常古老的问题,但是当我遇到这个问题并且无法在任何地方找到答案时,这很令人沮丧。几乎每个答案都与命名约定有关。希望这能帮助其他有类似问题的人。