我在我的Spring Boot项目中使用QueryDSL并计划使用Spring的Web支持(current query dsl web docs)。问题是,我找不到任何关于使用不同运算符的信息。如何定义not equals
或matches regex
操作?乍一看,它所做的只是将您的?fieldname=value
格式GET
请求转换为您在存储库中设置的预定义操作。我可以以允许同一字段的多个操作的方式扩展它吗?
例。:
目前我可以通过传递URL参数来获取QueryDsl qazxsw poi,例如qazxsw poi:
Predicate
但是,正如我链接的文档所述,我只能为某个字段定义单个操作。如果我想要用户,?user.company.id=1
从哪里开始,仍然有可能查询完全匹配? (@Controller
class UserController {
@Autowired UserRepository repository;
@RequestMapping(value = "/", method = RequestMethod.GET)
Page<User> getUsers(@QuerydslPredicate(root = User.class) Predicate predicate,
Pageable pageable) {
return repository.findAll(predicate, pageable);
}
}
和user.lastName
也许)
?lastName=Xyz,contains
定义了每个字段的操作,但是您只能定义如何处理该特定字段,不可能添加多个操作。
也许我不能用QueryDSL做到这一点,但是一般在Spring启动时如何将过滤器应用于搜索查询?
我正在做那样的事情。虽然我尝试做更复杂的动作时遇到了一些限制。我在一些步骤中所做的事情:
?lastName=Xyz,equals
的新接口QuerydslBinderCustomizer
(注意用户的Q,你想要QueryDSL自动生成的类而不是你的实体)。MyBinderCustomizer<T extends EntityPath<?>>
方法。例如:QuerydslBinderCustomizer<QUser>
customize
(再次注意Q)。这将允许您使用这些操作:
public BooleanExpression StringExpression.like(java.lang.String) public BooleanExpression StringExpression.notLike(java.lang.String) public BooleanExpression StringExpression.notEqualsIgnoreCase(java.lang.String) public BooleanExpression StringExpression.containsIgnoreCase(java.lang.String) public BooleanExpression StringExpression.likeIgnoreCase(java.lang.String) public BooleanExpression StringExpression.startsWithIgnoreCase(java.lang.String) public BooleanExpression StringExpression.endsWithIgnoreCase(java.lang.String) public BooleanExpression StringExpression.equalsIgnoreCase(java.lang.String) public BooleanExpression StringExpression.startsWith(java.lang.String) public BooleanExpression StringExpression.endsWith(java.lang.String) public BooleanExpression StringExpression.matches(java.lang.String) public BooleanExpression StringExpression.contains(java.lang.String) public BooleanExpression StringExpression.isEmpty() public BooleanExpression StringExpression.isNotEmpty() public BooleanExpression SimpleExpression.isNull() public BooleanExpression SimpleExpression.isNotNull() public BooleanExpression SimpleExpression.ne(java.lang.Object) public BooleanExpression SimpleExpression.eq(java.lang.Object)
@Override
public default void customize(QuerydslBindings bindings, T root) {
bindings.bind(String.class).all(MyBinderCustomizer::applyStringComparison);
}
static BooleanExpression applyStringComparison(Path<String> path, Collection<? extends String> strings) {
BooleanExpression result = null;
for (String s : strings) {
try {
final String[] parts = s.split(",");
final String operator = parts[0];
final String value = parts.length > 1 ? parts[1] : null;
final Method method = Arrays.stream(path.getClass().getMethods())
.filter(m -> operator.equals(m.getName()))
.filter(m -> BooleanExpression.class.equals(m.getReturnType()))
.filter(m -> m.getParameterTypes().length == (value == null ? 0 : 1))
.filter(m -> value == null || m.getParameterTypes()[0].equals(String.class) || m.getParameterTypes()[0].equals(Object.class))
.findFirst().get();
final BooleanExpression be;
if (value == null) {
be = (BooleanExpression) method.invoke(path);
} else {
be = (BooleanExpression) method.invoke(path, value);
}
result = result == null ? be : result.and(be);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
return result;
}
库扩展MyBinderCustomizer<QUser>
不仅包含字符串字段,还包括Number和Enum字段。它需要一些特殊的配置才能使它适用于非String字段,如Spring Data QueryDSL Value Operators所述:
值运算符在基于字符串的属性/字段上无效工作。但是这些运算符不能很好地处理非字符串值,如Number或Enum,因为默认情况下Spring Data QueryDSL web support解析注释here,用于在RESTful方法(也就是RestController方法)上注释搜索处理方法,根据指导执行强类型Querydsl的设计原则,即它试图将从HTTP请求接收的值转换为在相应的Q-Class中定义的精确类型。这在没有值运算符的情况下运行良好,并且与Querydsl承诺允许类型安全查询但是阻碍值运算符执行其技巧的路径。
该库提供了两种方法使运算符适用于非String字段:
QuerydslPredicateArgumentResolver
中的ConversionService,以便将所有查询参数视为String(丢失强类型)两种方法都有详细记录,以及它们的用例和缺点。
我目前正在评估方法1,因为这符合我们的用例,但我需要扩展它以适应DateTime字段和一些自定义运算符。