【问题标题】:Filter JPA repository by multiple optional parameters通过多个可选参数过滤 JPA 存储库
【发布时间】:2018-06-15 17:05:03
【问题描述】:

我有一个简单的 REST 服务,它返回包含大约 20 个字段的用户配置文件实体。

我需要实现一个功能来过滤需要姓氏的数据,但所有其他字段(名字、年龄、城市、州、邮编等)都是可选的。

有没有办法使用JpaRepository 来做到这一点,而无需为每个patamenters 组合创建大量if/else 语句?

【问题讨论】:

    标签: java spring-mvc spring-boot spring-data-jpa


    【解决方案1】:

    JpaRepository 接口还实现了 QueryByExampleExecutor 接口,该接口提供了 findAll 方法,用于使用 Query by Example (QBE) 技术获取数据。该方法确实适用于您的场景,并且当实体有很多字段并且您希望用户能够通过其中一些字段过滤实体时,它实际上是理想的。

    假设实体是 Person 并且您想要创建端点来获取属性等于指定属性的人员。这可以通过以下代码来完成:

    实体类:

    @Entity
    public class Person implements Serializable {
        private Long id;
        private String firstName;
        private String lastName;
        private Integer age;
        private String city;
        private String state;
        private String zipCode;
    }
    

    控制器类:

    @Controller
    public class PersonController {
        private PersonService service;
        private PersonController(PersonService service) {
            this.service = service;
        }
    
        @GetMapping
        public List<Person> getMatchingPersons(@RequestBody Person personFilter) {
            return service.findMatchingPersons(personFilter);
        }
    }
    

    服务类:

    @Service
    public class PersonService {
        private PersonRepository repository;
        private PersonService(PersonRepository repository) {
            this.repository = repository;
        }
    
        public List<Person> getMatchingPersons(Person personFilter) {
            return repository.findAll(Example.of(personFilter));
        }
    }
    

    存储库类:

    @Repository
    public class PersonRepository implements JpaRepository<Person, Long> {
    }
    

    【讨论】:

      【解决方案2】:

      这是JPA criteria 的一个用例(自 JPA2 起可用)。
      实际上,当您想编写动态查询时,最重要的是,您不想为每个组合硬编码 JPQL 查询,也不希望连接 JPQL 的块,因为这很容易出错并且在编译时未检查。

      请注意,在任何情况下(CriteriaJPQL),如果客户端已指定它能够在查询构建中将它们考虑在内,您应该检查每个可能的选项。

      现在,当您实现JPARepository 接口时,您有两种方法:

      • 使用JpaSpecificationExecutor 接口提供的List&lt;T&gt; findAll(@Nullable Specification&lt;T&gt; spec);,您也可以在自定义存储库中实现该接口。

      • 使用您自己的接口丰富JPARepository,该接口定义了一个方法findAll(),并将一个包含研究值的对象作为参数。
        然后创建一个具体的类来实现JPARepository。 您将有能力注入EntityManager 并使用Criteria API。

      【讨论】:

      • 我可以使用规范来做到这一点。对于那些尝试使用规范的人来说一点点,大多数解决方案都使用 MetaModel Classes(ClassName_),只需在字符串中给出字段名称即可跳过它。
      【解决方案3】:
      • 最好在 REST 响应。
      • 在您的 DTO 中,您只能映射实体中的必填字段,并且 忽略其他可选参数。

      看看这个http://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application

      【讨论】:

        猜你喜欢
        • 2016-07-28
        • 1970-01-01
        • 1970-01-01
        • 2019-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-17
        • 2020-02-03
        相关资源
        最近更新 更多