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

查看:102
本文介绍了如何使用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实体:

@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

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

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'.

推荐答案

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扩展

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

接下来,我们必须创建不区分大小写的喜欢"过滤器.为此,我们从QuerydslBinderCustomizer扩展了仓库,并覆盖了customize方法(在仓库中):

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

要使其正常工作,我们必须在控制器方法的@QuerydslPredicate中添加参数bindings:

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支持,我们必须将以下依赖项和插件添加到我们的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类".

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

您可以在我的仓库中找到完整的示例演示: sb-querydsl-sd-demo 邮递员此演示的API文档-此处:

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天全站免登陆