,java,spring,spring-boot,jpa"/>

首页 > 解决方案 > JpaSpecificationExecutor似乎不像 JpaRepository 那样工作

问题描述

通常在使用 JpaRepository 接口时,我倾向于提及接口中的方法,这些方法将在我的服务类中使用。例子:

public interface UserRepository extends JpaRepository<User, Integer> {

    List<User> findAll(); // Usually I mention the methods this way in the interface.

}

这非常有效。但是,当使用 JpaSpecificationExecutor 接口时,如果我在接口中提及方法,则会引发错误,例如 - failed to create query method...。

如果我不提及该方法,它会按预期工作。有人可以解释一下 Spring 中的这种奇怪行为吗?

public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {

    List<User> findAll(UserSpecification user); // If I do not mention this method here, it works perfectly.

}

标签: javaspringspring-bootjpa

解决方案


  1. List<User> findAll()在扩展接口之一(即 JpaRepository<User, Integer>)中声明。在扩展接口中重新声明方法不是错误,只要签名相同;它根本没有任何效果。这个事实与 Spring Data 无关;这就是 Java 的工作原理。

  2. List<User> findAll(UserSpecification)未在任何扩展接口中声明请注意,通过实现JpaSpecificationExecutor<User>,您的接口将继承带有签名的方法声明List<User> findAll(Specification<User>),这并不相同。这两种方法具有不同的签名,因为Specification<User>UserSpecification.

  3. 当然,您可以向存储库接口添加新方法,只要它们代表简单的查询,不带Specification参数,例如User findByName(String name)Spring Data 将在运行时自动为这些方法生成实现

  4. 如果它们的参数表示自定义类型扩展,或者 Spring Data 无法识别的任何其他类型,则您不能向存储库接口添加新方法Specification,因为在运行时,Spring Data 将无法为此类方法生成实现——它根本不会了解如何处理这种方法

使用规范,您应该使用JpaSpecificationExecutor提供的方法。我不明白为什么你会想要一个类似的方法List<User> findAll(UserSpecification user)- 如果UserSpecificationextends Specification<User>,那么继承的List<User> findAll(Specification<User>)就可以了。


推荐阅读