gpt4 book ai didi

java - 使用 Java 8 谓词的 JPA 存储库过滤器

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:07:39 25 4
gpt4 key购买 nike

我在一个使用 Spring Boot 的面试测试中有一个要求,我必须创建一个端点来接受一堆可选的请求参数,然后根据这些参数返回一个汽车列表,如汽车型号、车牌、发动机类型、制造商、司机、租给的公司等等。汽车、司机和制造商都是独立的实体。

我在 JPARepository 中使用单个 JPQL 查询实现此功能,该查询实现 LEFT JOINS 并在 where 子句中进行过滤,例如 licensePlate = licensePlateParameter OR licensePlatParameter is null 等。

该解决方案运行良好,但面试官表示该解决方案具有可扩展性和可维护性。我应该使用谓词来实现它。有人可以给我举个例子,我如何使用更易于维护的谓词来实现这样的功能?一些带有代码的示例将不胜感激。

我认为我很聪明,通过检查参数是否为 null 来满足可选参数的需求,并在一次调用中找到记录。我想到的另一个与此相关的问题是从数据库中获取所有记录然后使用谓词过滤它真的是一个好习惯吗?还有当我们涉及多个对象/实体时如何过滤,可以为单个类型创建谓词。

@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);

最佳答案

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);
}

它还允许您编写连接操作:

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);
};
}

您可以在条件中返回 null,这使您可以将这些规范设为“可选”。之后,您可以使用 Specifications.where() 来组合这些条件:

 Specification<Car> spec = Specifications
.where(withLicensePlate(licensePlate))
.and(withRating(rating))
.and(withName(name))
.and(withSeatType(seatType));

如果您像我在本例中那样编写单独的规范,则可以在必要时重复使用它们。否则,您将不得不编写特定于操作的规范,而面试官可能也不会发现可扩展性。

编写规范后,您必须从 JpaSpecificationExecutor 接口(interface)扩展您的存储库并使用 findAll(Specification) 方法。

关于java - 使用 Java 8 谓词的 JPA 存储库过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52280227/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com