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

5

我已经按照这个问题的答案,向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)

这似乎是因为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> {

}

以下是结果:

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)

发布你的代码。告诉我们你想要实现什么。 - JB Nizet
请分享你的实现代码。当你使用Spring Data JPA的自定义实现时,命名规范很重要。例如,如果你的接口名称是AccountRepository,那么实现类的名称应该是AccountRepositoryImpl - Nitin Arora
我假设链接问题中的代码是他使用的;它应该被编辑到这个问题中。尽管如此,我投票支持“保持开放”。 - o11c
我按照如何将自定义方法添加到Spring Data JPA的说明遇到了完全相同的问题,但是找不到解决方案或原因。唯一有效的方法是在Repository接口中使用默认方法,但如果需要注入EntityManager或类似的内容,则没有太大帮助。我在Java EE环境中使用Spring data,也许在使用Spring Boot时不会出现这个问题。 - Meini
1个回答

1

简而言之

我遇到了类似的问题,花了很长时间才找到解决方法。 在我的情况下,原来是我的实现类(Impl class)位于不同的包中。例如

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

那个方法不起作用。通过将实现类移动到接口包下方解决了这个问题。

Repository Interface.      : com.example.dao.repo.MyRepository
Custom Interface           : com.example.dao.repo.MyRepositoryCustom
Custom Implementation Class: com.example.dao.repo.impl.MyRepositoryCustomImpl

分析

看起来,Spring Data 创建存储库的方式是尝试检测是否存在所谓的片段(自定义实现)。在它可以检测到自定义接口但无法检测到 Impl 类(无论是由于命名约定还是包位置),Spring 将会回退到其他方法来生成该方法,从而导致误导性的消息“没有 xxx 属性适用于 xxx”。

Spring Data 文档实际上对此进行了说明,但很微妙,容易被忽略:

存储库基础架构尝试通过扫描位于其发现存储库下面的类来自动检测自定义实现片段。这些类需要遵循追加后缀默认为 Impl 的命名约定。

如果您将 Spring Data 的调试级别日志打开并加载了片段类,则应该能够看到以下日志。否则,这可能意味着 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

P.S

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接