如何使用 Querydsl 和 Spring Data 轻松实现“REST API 查询语言"来过滤实体? [英] How to easy implement 'REST API query language' with Querydsl and Spring Data to filter the entities?

查看:23
本文介绍了如何使用 Querydsl 和 Spring Data 轻松实现“REST API 查询语言"来过滤实体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用 Spring Data 轻松实现一种REST API 查询语言"来过滤实体?

How to easy implement a kind of 'REST API query language' with Spring Data to filter the entities?

例如,对于以下 Person 实体:

For example, for the following Person entity:

@Data
@Entity
public class Person {

  @Id
  @GeneratedValue
  private Long id;

  private LocalDate dob; // date of birth

  private String name;

  @Formula("timestampdiff('year', dob, now())")
  private Integer age;

  public Person(String name, LocalDate dob) {
    this.name = name;
    this.dob = dob;
  }
}

我想通过这样的请求获取它的数据:

I would like to get its data with such a request:

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

ie: '获取name中包含jo"(不区分大小写)且age等于18的所有人的第一页,按排序名称按降序排列'.

I.e.: 'get the 1st page of all people whose name contains "jo" (case insensitive) and whose age is equal to 18, sorting by name in descending order'.

推荐答案

借助Querydsl Web SupportWeb 支持 Spring Data 扩展,我们可以轻松实现一种REST API 查询语言"来过滤我们的实体.

With help of Querydsl Web Support, the part of Web support Spring Data extension, we can easy implement a kind of 'REST API query language' to filter our entities.

我们只需要做到以下几点:

All we need is do the following:

1) 从 QuerydslPredicateExecutor 扩展我们的存储库,

1) extend our repository from QuerydslPredicateExecutor,

2) 将带有注释 @QuerydslPredicatePredicate 作为参数添加到我们的 REST 控制器方法中

2) add Predicate with annotation @QuerydslPredicate, as argument, to our REST controller method

3) 在存储库的 findAll 方法中使用此谓词:

3) use this predicate in findAll method of the repository:

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

@RequiredArgsConstructor
@RestController
@RequestMapping("/people")
public class PersonController {

    private final PersonRepo personRepo;

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

然后我们就可以请求我们的数据了:

Then we will be able to request our data:

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

接下来我们必须制作不区分大小写的like"过滤器.为此,我们从 QuerydslBinderCustomizer 扩展我们的 repo 并覆盖它的 customize 方法(就在 repo 中):

Next we have to make case insensitive 'like' filter. To do this we extend our repo from QuerydslBinderCustomizer and override its customize method (right in the repo):

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

    @Override
    default void customize(QuerydslBindings bindings, QPerson person) {

        // Make case-insensitive 'like' filter for all string properties 
        bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
    }
}

为了使它起作用,我们必须将参数 bindings 添加到控制器方法的 @QuerydslPredicate 中:

To make it works we have to add parameter bindings to @QuerydslPredicate of our controller method:

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

现在我们可以按照问题中的要求请求我们的数据:

Now we can request our data as asked in the question:

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

使用 QuerydslBinderCustomizer 我们可以实现更复杂的过滤器,例如 betweengreater or equal 过滤器(将此代码添加到 customize 方法):

With QuerydslBinderCustomizer we can implement more complex filters, for example between and greater or equal filters (add this code to customize method):

bindings.bind(person.age).all((path, value) -> {
    Iterator<? extends Integer> it = value.iterator();
    Integer from = it.next();
    if (value.size() >= 2) {
        Integer to = it.next();
        return Optional.of(path.between(from, to)); // between
    } else {
        return Optional.of(path.goe(from)); // greater or equal
    }
});

如果我们在请求中指定两个 age 参数,那么我们将获得年龄这些参数之间的所有记录.如果我们只指定一个 age 参数 - 我们会得到年龄大于或等于该值的记录.

If we specify two age parameters in the request then we get all records with the age between these parameters. If we specify only one age parameter - we get records with the age is greater or equal that value.

GET /people?age=18&age=30

...获取所有年龄在 18 到 30 岁之间的人

GET /people?age=18

...获取所有年龄大于或等于 18 岁的人

最后我们可以从过滤器中排除一些不必要的属性,例如实体id(将此代码添加到customize方法中):

In the end we can exclude some unnecessary properties from the filter, for example the entity id (add this code to customize method):

bindings.excluding(person.id);

要使用 Querydsl Web Support,我们必须将这些依赖项和插件添加到我们的 Spring Boot 项目中:

To use Querydsl Web Support we have to add these dependencies and plugin to our Spring Boot project:

<dependencies>
    <!-- ... -->

    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- ... -->

        <plugin>
            <groupId>com.mysema.maven</groupId>
            <artifactId>apt-maven-plugin</artifactId>
            <version>1.1.3</version>
            <executions>
                <execution>
                    <goals>
                        <goal>process</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>target/generated-sources/annotations</outputDirectory>
                        <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

然后,重要的是,编译项目以构建我们实体的Q-classes".

Then, it's important, compile the project to build 'Q-classes' of our entities.

您可以在我的 repo 中找到完整的示例演示:sb-querydsl-sd-demoPostman 此演示的 API 文档 - 此处:带有 Querydsl 和 Spring Data 的 REST 查询语言.

Full example demo you can find in my repo: sb-querydsl-sd-demo, and Postman API-docs of this demo - here: REST query language with Querydsl and Spring Data.

这篇关于如何使用 Querydsl 和 Spring Data 轻松实现“REST API 查询语言"来过滤实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆