【问题标题】:How to add a comparator to querydsl Predicate?如何向querydsl Predicate添加比较器?
【发布时间】:2019-09-02 14:09:57
【问题描述】:

我有以下网络服务,可自动将获取参数查询转换为数据库选择:

public interface PersonRepo extends
        JpaRepository<Person, Long>,
        QuerydslPredicateExecutor<Person> {

}

@GetMapping
public ResponseEntity getFiltered(
    @QuerydslPredicate(root = Person.class) Predicate predicate, Pageable pageable) {
       return ResponseEntity.ok(personRepo.findAll(predicate, pageable)));
    )
}

例如可以执行以下查询:

GET /people?name=John&age=18
GET /people?name=John&age=18&page=1&sort=name,desc

问题:我想按如下方式应用比较器查询:

GET /people?name=John&age>18
GET /people?name=John&age>18&age<30
GET /people?name=John&age<30

问题:我怎样才能做到这一点?至少后面的查询不起作用。

【问题讨论】:

  • Spring Data 不支持此类查询。您可以自定义绑定(并使用别名,例如 agegt=18)baeldung.com/rest-api-search-querydsl-web-in-spring-data-jpa,但 OData (Olingo) 或 GraphQL 实现对于诸如此类的灵活查询可能会更好。
  • 你能举个例子来说明使用例如agegt吗?因为那将是我的Person.class 上没有的属性,那么我怎样才能将它放入QPerson.class 中呢?
  • @membersound 请查看我的帖子(1,2),希望它们会有所帮助。关于你的第二个问题,如果Person 与另一个实体有关联,例如包含age 属性的Data,请尝试使用前缀data. 来解决它,例如:data.age,也许它会有所帮助你。尽管如此,正如@AlanHay 已经说过的那样,Querydsl 并不是您任务的最佳解决方案,IMO 最好使用 Specifications/Criteria API 来构建您自己的“查询语言”(请参阅​​我的第二个链接)。

标签: java spring spring-data-jpa spring-data-rest querydsl


【解决方案1】:

我通过为字段定义占位符并使用QuerydslBinderCustomizer找到了解决方案:

public interface PersonRepo extends
        JpaRepository<Person, Long>,
        QuerydslPredicateExecutor<Person>,
        QuerydslBinderCustomizer<Person> {
    default void customize(final QuerydslBindings bindings, final QPerson person) {
        bindings.bind(cache.ageMin).first((path, value) -> person.age.goe(value));
        bindings.bind(cache.ageMax).first((path, value) -> person.age.loe(value));
    }
}

当然,年龄字段必须作为瞬态字段存在,以便 querydsl 知道它们:

@Entity
class Person {
    @Transient
    @QueryType(PropertyType.NUMERIC)
    public int ageMin;

    @Transient
    @QueryType(PropertyType.NUMERIC)
    private int ageMax;
}

【讨论】:

    【解决方案2】:

    您可以使用单个绑定并使用来自Query DSL value operators 的表达式。

    public interface PersonRepo extends
        JpaRepository<Person, Long>,
        QuerydslPredicateExecutor<Person>,
        QuerydslBinderCustomizer<Person> {
        default void customize(final QuerydslBindings bindings, final QPerson person) {
            bindings.bind(cache.age).all((path, values) -> ExpressionProviderFactory.getPredicate(path, values));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-02-01
      • 2016-12-26
      • 2016-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-03
      相关资源
      最近更新 更多