[英]Optional parameter in query method with explicit null support in Spring JPA
如这个答案所示,我想忽略过滤器中未指定的字段,但我也想要一种方法来明确指定字段是否为 null。
基本上是这样的:
class User {
String f1;
String f2;
String f2;
}
class UserFilter {
Optional<String> f1;
Optional<String> f2;
Optional<String> f3;
}
class UserService {
List<User> findBy(UserFilter u){
userRepository.findAll(Example.of(user));
}
}
如果Optional<String>
是 null 那么它应该忽略该字段但如果它不是 null 并且是空的那么我应该明确检查数据库中的可空性条件。
例如,如果f1
和f3
不是 null 并且不为空并且f2
是findby
那么它应该通过f1
和f3
查找并忽略f2
的值但是如果f2
的值不是 null 并且是空的那么它应该返回f2
是 null 的实体数据库。
首先,您需要在ExampleMatcher
中包含null
字段,因为默认匹配器不包含它。
其次,如果可选的是null
,则需要排除此字段。
简而言之,您可以编写这样的方法:
public static Example<User> getExampleByUserFilter(UserFilter userFilter) {
User user = new User();
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAll()
.withIgnorePaths("id") // (1)
.withIncludeNullValues();
Optional<String> optionalF1 = userFilter.getF1();
if (optionalF1.isPresent()) {
if (!optionalF1.get().isBlank()) {
user.setF1(optionalF1.get());
}
} else {
exampleMatcher = exampleMatcher.withIgnorePaths("f1");
}
Optional<String> optionalF2 = userFilter.getF2();
if (optionalF2.isPresent()) {
if (!optionalF2.get().isBlank()) {
user.setF2(optionalF2.get());
}
} else {
exampleMatcher = exampleMatcher.withIgnorePaths("f2");
}
// other fields ..
return Example.of(user, exampleMatcher);
}
我们打个例子,看看sql查询output:
...
UserFilter userFilter1 = new UserFilter(
Optional.of("f1"),
Optional.empty(),
Optional.of("f3"));
UserFilter userFilter2 = new UserFilter(
Optional.of("f1"),
Optional.of(""),
Optional.of("f3"));
userRepository
.findAll(getExampleByUserFilter(userFilter1));
userRepository
.findAll(getExampleByUserFilter(userFilter2));
...
此示例的控制台 output:
Hibernate: select ... from user user0_
where user0_.f1=? and user0_.f3=?
Hibernate: select ... from user user0_
where user0_.f1=? and user0_.f3=? and (user0_.f2 is null)
(1) 这里重要的是你需要在第一步中用withIgnorePaths(...)
消除所有你不会在过滤器中使用的字段。
OR
我建议使用Specifications and Querydsl
进行此类条件操作。
您也可以从JpaSpecificationExecutor
扩展并从Example
中获取带有QueryByExamplePredicateBuilder
的Predicate
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.