我在Spring Boot项目中使用QueryDSL,并计划对其使用Spring的Web支持(current query dsl web docs)。问题是,我找不到有关使用不同运算符的任何信息。如何定义not equals
或matches regex
操作?乍一看,它所做的只是将您的?fieldname=value
格式GET
请求转换为您在存储库中设置的预定义操作。我可以以允许对同一字段进行多个操作的方式扩展它吗?
例。:
目前,我可以通过传递URL参数来获取QueryDsl 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
和?lastName=Xyz,equals
)QuerydslBinderCustomizer
定义每个字段的操作,但是您只能定义如何处理该特定字段,无法添加多个操作。也许我无法使用QueryDSL进行此操作,但是通常在Spring Boot中如何将过滤器应用于搜索查询?
最佳答案
我正在做类似的事情。尽管在尝试执行更复杂的操作时遇到一些限制。我在某些步骤中所做的事情:
创建一个扩展MyBinderCustomizer<T extends EntityPath<?>>
的新接口QuerydslBinderCustomizer<QUser>
(请注意,“用户Q”,您要QueryDSL自动生成的类而不是您的实体)。
实现customize
方法。例如:
@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;
}
请注意,您应该更改值/运算符的顺序,以便可以调用isNull之类的无值运算符。
您的存储库必须扩展
MyBinderCustomizer<QUser>
(再次注意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)
公共BooleanExpression StringExpression.isEmpty()
公共BooleanExpression StringExpression.isNotEmpty()
公共BooleanExpression SimpleExpression.isNull()
公共BooleanExpression SimpleExpression.isNotNull()
公共BooleanExpression SimpleExpression.ne(java.lang.Object)
公共BooleanExpression SimpleExpression.eq(java.lang.Object)