gpt4 book ai didi

spring - 如何使用 Querydsl 和 Spring Data 轻松实现 'REST API query language' 以过滤实体?

转载 作者:行者123 更新时间:2023-12-04 18:44:16 36 4
gpt4 key购买 nike

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

例如,对于以下 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;
}
}

我想通过这样的请求获取其数据:
GET /people?name=jo&age=18&page=1&sort=name,desc

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

最佳答案

Querydsl Web Support 的帮助下,Web support Spring Data extension 的一部分,我们可以轻松实现一种“REST API 查询语言”来过滤我们的实体。

我们只需要执行以下操作:

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

2) 将带有注释 Predicate@QuerydslPredicate 作为参数添加到我们的 REST Controller 方法中

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

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

然后我们将能够请求我们的数据:
GET /people?name=John&age=18&page=1&sort=name,desc

接下来我们必须制作不区分大小写的“like”过滤器。为此,我们从 QuerydslBinderCustomizer 扩展我们的 repo 并覆盖其 customize 方法(就在 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 添加到我们的 Controller 方法的 @QuerydslPredicate 中:

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

现在我们可以按照问题中的要求请求我们的数据:
GET /people?name=jo&age=18&page=1&sort=name,desc

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

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 参数 - 我们会得到年龄大于或等于该值的记录。
GET /people?age=18&age=30

...让所有年龄在 18 到 30 岁之间的人
GET /people?age=18

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

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

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

<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”。

您可以在我的 repo 中找到完整的示例演示: sb-querydsl-sd-demoPostman 这个演示的 API 文档 - 在这里: REST query language with Querydsl and Spring Data

关于spring - 如何使用 Querydsl 和 Spring Data 轻松实现 'REST API query language' 以过滤实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51127468/

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