gpt4 book ai didi

spring-boot - JPA 规范示例

转载 作者:行者123 更新时间:2023-12-04 02:19:37 24 4
gpt4 key购买 nike

Spring Boot 在这里。我正试图将我的头环绕在 JpaRepositoriesSpecifications当在实现复杂查询的上下文中使用时,我很难在几个项目上看到“森林穿过树木”。
Specification 的典型示例如下:

public class PersonSpecification implements Specification<Person> {
private Person filter;

public PersonSpecification(Person filter) {
super();
this.filter = filter;
}

public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> cq,
CriteriaBuilder cb) {
Predicate p = cb.disjunction();

if (filter.getName() != null) {
p.getExpressions()
.add(cb.equal(root.get("name"), filter.getName()));
}

if (filter.getSurname() != null && filter.getAge() != null) {
p.getExpressions().add(
cb.and(cb.equal(root.get("surname"), filter.getSurname()),
cb.equal(root.get("age"), filter.getAge())));
}

return p;
}
}

在此 toPredicate(...)方法,怎么办 Root<Person>CriteriaQuery代表?最重要的是,听起来您需要创建一个 Specification impl 为您要应用的每种类型的过滤器,因为每个规范都被翻译成一个且只有一个谓词...听起来我需要写一个 LastnameMatchingSpecification<Person>以及 AgeGreaterThanSpecification<Person> .有人可以为我确认或澄清这一点吗?!

最佳答案

一开始这对我来说也很困难,但现在我可以轻松地进行动态查询,每个表只有一个规范(当需要高级搜索时)

想想这些对象,如:

  • 根是你的 table 。
  • CriteriaQuery 是您的查询,适用于应用不同、子查询、排序依据等。
  • CriteriaBuilder 是您的条件,有助于创建您的 where 子句

  • ——

    始终以列表开头,然后根据您的需要在最后使用 AND/OR 条件压缩它们。
    public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
    List<Predicate> predicates = new ArrayList<>();

    if(filter.getName() != null) {
    predicates.add(cb.equal(root.get("name"), filter.getName());
    }
    if(filter.getSurname() != null) {
    predicates.add(cb.equal(root.get("surname"), filter.getSurname());
    }
    if(filter.getAge() != null) {
    predicates.add(cb.equal(root.get("age"), filter.getAge());
    }
    if(predicates.isEmpty()){
    predicates.add(cb.equal(root.get("id"), -1);
    /*
    I like to add this because without it if no criteria is specified then
    everything is returned. Because that's how queries work without where
    clauses. However, if my user doesn't provide any criteria I want to
    say no results found.
    */
    }

    return query.where(cb.and(predicates.toArray(new Predicate[0])))
    .distinct(true).orderBy(cb.desc(root.get("name")).getRestriction();
    }

    现在我的用户可以在此处传递这 3 个字段的任意组合,此逻辑将动态构建查询以包含它们的条件。

    例如
    姓名 = 约翰和姓氏 = Doe 和年龄 = 41
    或者
    姓名 = 约翰,年龄 = 41
    或者
    姓名 = 约翰
    等等。

    最后,在搜索字符串时,我建议使用 cb.like 而不是 cb.equal ,以便它可以使您的搜索能够部分搜索 % 由用户或前端系统传递。

    请记住,默认情况下 cb.like 不区分大小写,它需要与 cb.lower 或 cb.upper 结合使用,例如:
     predicates.add(cb.like(cb.lower(root.get("name"), filter.getName().toLowercase());

    希望这可以帮助 !

    关于spring-boot - JPA 规范示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48647847/

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