Das*_*Boy 5 java predicate spring-data-jpa spring-boot
我在使用 Spring Boot 的一次面试测试中有一个要求,我必须创建一个端点,该端点接受一堆可选的请求参数,然后根据这些参数返回汽车列表,例如汽车型号、车牌、发动机类型、制造商,司机,公司等。汽车,司机和制造商都是独立的实体。
我在 JPARepository 中使用单个 JPQL 查询实现了这个功能,该查询实现了 LEFT JOINS 并在 where 子句中过滤,如 licensePlate = licensePlateParameter OR licensePlatParameter is null 等。
该解决方案有效,但面试官表示该解决方案具有可扩展性和可维护性。我应该使用谓词来实现它。有人可以向我展示一个示例,我如何使用更易于维护的谓词来实现此类功能?一些带有代码的示例将不胜感激。
我认为我很聪明,通过检查参数是否为空来满足可选参数和在单个调用中找到的记录。我想到的另一个与此相关的问题是,从 DB 获取所有记录然后使用谓词对其进行过滤真的是一个好习惯吗?还有当我们涉及多个对象/实体时如何过滤,可以为单个类型创建谓词。
@Query("SELECT d FROM Driver d LEFT JOIN d.car c WHERE (d.name = :name OR :name is null) "
+ "and (c.licensePlate = :licensePlate OR :licensePlate is null) "
+ "and (c.rating = :rating OR :rating is null) " and so on
List<Driver> findByAttributes(@Param("name") String name,
@Param("licensePlate") String licensePlate,
@Param("rating") Integer rating,
and so on);
Run Code Online (Sandbox Code Playgroud)
Spring 对 JPA 标准 API(使用谓词)有一个包装器,称为规范 API。
编写规范时您可以执行以下操作,为每个标准编写规范:
public static Specification<Car> withLicensePlate(String licensePlate) {
return (root, query, cb) -> licensePlate == null ? null : cb.equal(root.get("licensePlate"), licensePlate);
}
public static Specification<Car> withRating(String rating) {
return (root, query, cb) -> rating == null ? null : cb.equal(root.get("rating"), rating);
}
public static Specification<Car> withName(String name) {
return (root, query, cb) -> name == null ? null : cb.equal(root.get("name"), name);
}
Run Code Online (Sandbox Code Playgroud)
它还允许您编写连接操作:
public static Specification<Car> withSeatType(String type) {
return (root, query, cb) -> {
return type == null ? null : cb.equal(root.join("interior", JoinType.LEFT).get("type"), type);
};
}
Run Code Online (Sandbox Code Playgroud)
您可以null在一个条件内返回,这允许您将这些规范设为“可选”。之后,您可以使用Specifications.where()组合这些条件:
Specification<Car> spec = Specifications
.where(withLicensePlate(licensePlate))
.and(withRating(rating))
.and(withName(name))
.and(withSeatType(seatType));
Run Code Online (Sandbox Code Playgroud)
如果你像我在这个例子中所做的那样编写单独的规范,你可以在必要时重新使用它们。否则,您将不得不编写特定于操作的规范,而面试官也可能不会发现它具有可扩展性。
编写规范后,您必须从JpaSpecificationExecutor接口扩展您的存储库并使用该findAll(Specification)方法。
| 归档时间: |
|
| 查看次数: |
11383 次 |
| 最近记录: |