gpt4 book ai didi

spring - 使用 Spring JPA 规范进行多列搜索

转载 作者:行者123 更新时间:2023-12-03 03:26:02 25 4
gpt4 key购买 nike

我想在 Spring-Boot 后端创建多字段搜索。如何使用 Specification<T> 执行此操作?

环境

Springboot
Hibernate
Gradle
Intellij

前端的UI是一个Jquery数据表。每列允许应用单个字符串搜索词。跨多列的搜索词由 and 连接。 .

enter image description here

我已经将来自前端的过滤器填充到 Java 对象中。

第 1 步扩展JPA规范执行器

public interface SomeRepository extends JpaRepository<Some, Long>, PagingAndSortingRepository<Some, Long>, JpaSpecificationExecutor {

第2步创建一个新类 SomeSpec

这就是我对代码的外观和工作方式感到困惑的地方。

每列都需要一个方法吗?什么是 Root,什么是 Criteria Builder?还需要什么?

我对 JPA 相当陌生,所以虽然我不需要任何人为我编写代码,但详细的解释会很好。

更新看来 QueryDSL 是解决这个问题的更简单、更好的方法。我正在使用 Gradle。我需要将 build.gradle 从 this 更改吗? ?

最佳答案

如果您不想使用 QueryDSL,则必须编写自己的规范。首先,您需要从JpaSpecificationExecutor扩展您的存储库就像你一样。确保添加通用名称 ( JpaSpecificationExecutor<Some> )。

之后,您必须在 the Spring docs 中创建三个规范(每列一个)。他们将这些规范定义为类中的静态方法。基本上,创建规范意味着您必须对 Specification<Some> 进行子类化。 ,只有一种方法可以实现, toPredicate(Root<Some>, CriteriaQuery<?>, CriteriaBuilder) .

如果您使用的是 Java 8,则可以使用 lambda 来创建匿名内部类,例如:

 public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> {
// ...
};
}
}

实际实现时,可以使用 Root到达特定节点,例如。 root.get("address")CriteriaBuilder另一方面是定义where子句,例如。 builder.equal(..., ...) .

在你的情况下,你想要这样的东西:

 public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.equal(root.get("address"), address);
}
}

或者如果您想使用 LIKE查询,您可以使用:

public class SomeSpecs {
public static Specification<Some> withAddress(String address) {
return (root, query, builder) -> builder.like(root.get("address"), "%" + address + "%");
}
}

现在您必须对要过滤的其他字段重复此操作。之后,您必须一起使用所有规范(使用 and() or() 、...)。然后您可以使用 repository.findAll(Specification) 根据该规范进行查询的方法,例如:

public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(withAddress(address))
.and(withName(name))
.and(withDate(date));
}

您可以使用静态导入来导入 withAddress() , withName()withDate()使其更易于阅读。 where()方法也可以静态导入(来自 Specification.where() )。

请注意,上述方法可能需要进行调整,因为如果地址字段是 null,则您不想对其进行过滤。 。您可以通过返回 null 来做到这一点,例如:

public List<Some> getSome(String address, String name, Date date) {
return repository.findAll(where(address == null ? null : withAddress(address))
.and(name == null ? null : withName(name))
.and(date == null ? null : withDate(date));
}

关于spring - 使用 Spring JPA 规范进行多列搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46970689/

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