有些时候,我们需要 Repository 所提供的功能是无法用 Spring Data 的方法命名约定来描述的,甚至无法用 @Query 注解设置查询来实现。尽管 Spring Data JPA 非常棒,但是它依然有其局限性,可能需要我们按照传统的方式来编写 Repository 方法:也就是直接使用 EntityManager。当遇到这种情况的时候,我们是不是要放弃 Spring Data JPA,重新按照 11.2.2 小节中的方式来编写 Repository 呢?
简单来说,是这样的。如果你需要做的事情无法通过 Spring Data JPA 来实现,那就必须要在一个比 Spring Data JPA 更低的层级上使用 JPA。好消息是我们没有必要完全放弃 Spring Data JPA。我们只需在必须使用较低层级 JPA 的方法上,才使用这种传统的方式即可,而对于 Spring Data JPA 知道该如何处理的功能,我们依然可以通过它来实现。
当 Spring Data JPA 为 Repository 接口生成实现的时候,它还会查找名字与接口相同,并且添加了 Impl 后缀的一个类。如果这个类存在的话,Spring Data JPA 将会把它的方法与 Spring Data JPA 所生成的方法合并在一起。对于 SpitterRepository 接口而言,要查找的类名为 SpitterRepositoryImpl。
为了阐述该功能,假设我们需要在 SpitterRepository 中添加一个方法,发表 Spittle 数量在 10,000 及以上的 Spitter 将会更新为 Elite 状态。使用 Spring Data JPA 的方法命名约定或使用 @Query 均没有办法声明这样的方法。最为可行的方案是使用如下的 eliteSweep() 方法。
注意,SpitterRepositoryImpl 并没有实现 SpitterRepository 接口。Spring Data JPA 负责实现这个接口。SpitterRepositoryImpl(将它与 Spring Data 的 Repository 关联起来的是它的名字)实现了 SpitterSweeper 接口,它如下所示: