Java 处理 QueryDSL 中的可选参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23750528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Handle optional parameters in QueryDSL
提问by Prashant Shilimkar
I am using QueryDSL with SpringData.
I have Table say, Employee
and I have created entity class say, EmployeeEntity
I have written following servicemethod
我在 SpringData 中使用 QueryDSL。我有表说,Employee
我已经创建了实体类说,EmployeeEntity
我写了以下服务方法
public EmployeeEntity getEmployees(String firstName, String lastName)
{
QEmployeeEntity employee = QEmployeeEntity.employeeEntity;
BooleanExpression query = null;
if(firstName != null)
{
query = employee.firstName.eq(firstName);
}
if(lastName != null)
{
query = query.and(employee.lastName.eq(lastName)); // NPException if firstName is null as query will be NULL
}
return empployeeDAO.findAll(query);
}
As in above I commented the NPException
. How to use QueryDSLfor optional Parameters in QueryDSLusing Spring Data?
如上所述,我评论了NPException
. 如何使用QueryDSL在可选参数QueryDSL使用Spring的数据?
Thank you :)
谢谢 :)
采纳答案by Timo Westk?mper
BooleanBuilder
can be used as a dynamic builder for boolean expressions:
BooleanBuilder
可以用作布尔表达式的动态构建器:
public EmployeeEntity getEmployees(String firstName, String lastName) {
QEmployeeEntity employee = QEmployeeEntity.employeeEntity;
BooleanBuilder where = new BooleanBuilder();
if (firstName != null) {
where.and(employee.firstName.eq(firstName));
}
if (lastName != null) {
where.and(employee.lastName.eq(lastName));
}
return empployeeDAO.findAll(where);
}
回答by Oliver Drotbohm
This is Java 101 actually: check for null
and initialize the query instead of concatenating predicates. So a helper method like this could do the trick:
这实际上是 Java 101:检查null
并初始化查询而不是连接谓词。因此,像这样的辅助方法可以解决问题:
private BooleanExpression createOrAnd(BooleanExpression left, BooleanExpression right) {
return left == null ? right : left.and(right);
}
Then you can simply do:
然后你可以简单地做:
BooleanExpression query = null;
if (firstName != null) {
query = createOrAnd(query, employee.firstName.eq(firstName));
}
if (lastName != null) {
query = createOrAnd(query, employee.lastName.eq(lastName));
}
…
Note, that I use createOrAnd(…)
even in the first clause simply for consistency and to not have to adapt that code in case you decide to add a new clause even before the one for firstName
.
请注意,我createOrAnd(…)
什至在第一个子句中使用只是为了保持一致性,如果您决定在 for 之前添加新子句,则不必修改该代码firstName
。
回答by ameen
if you check the QueryDSL implementation of null
:
如果您检查 QueryDSL 实现null
:
public BooleanExpression and(@Nullable Predicate right) {
right = (Predicate) ExpressionUtils.extract(right);
if (right != null) {
return BooleanOperation.create(Ops.AND, mixin, right);
} else {
return this;
}
}
which is supposedly what you want.
这应该是你想要的。
回答by EliuX
Base on what you need i would do this
根据您的需要,我会这样做
public List<EmployeeEntity> getEmployees(Optional<String> firstName, Optional<String> lastName)
{
BooleanExpression queryPredicate = QEmployeeEntity.employeeEntity.firstName.containsIgnoreCase(firstName.orElse("")).and(QEmployeeEntity.employeeEntity.lastName.containsIgnoreCase(lastName.orElse("")));
return empployeeDAO.findAll(queryPredicate);
}
First of all you should return a List
of EmployeeEntity
. Second, its better to use optional than checking if its null
, and you may pass Java 8's Optional
values obtained from optional RequestParam
ones like this:
首先,您应该返回一个List
of EmployeeEntity
。其次,使用 optional 比检查它是否更好null
,并且您可以传递Optional
从可选值获得的Java 8值RequestParam
,如下所示:
@RequestMapping(value = "/query", method = RequestMethod.GET)
public ModelAndView queryEmployee(@RequestParam(value = "firstName", required = false) Optional<String> firstName, @RequestParam(value = "lastName", required = false) Optional<String> lastName)
{
List<EmployeeEntity> result = getEmployees(firstName, lastName);
....
}
And a very important thing is to use the containsIgnoreCase
function in the predicate: its better than a typical like
cause its case insensitive.
一个非常重要的事情是containsIgnoreCase
在谓词中使用函数:它比like
不区分大小写的典型原因更好。
In my opinion you should use some approach like this:
在我看来,你应该使用这样的方法:
@Controller
class UserController {
@Autowired UserRepository repository;
@RequestMapping(value = "/", method = RequestMethod.GET)
String index(Model model, @QuerydslPredicate(root = User.class) Predicate predicate,
Pageable pageable, @RequestParam MultiValueMap<String, String> parameters) {
model.addAttribute("users", repository.findAll(predicate, pageable));
return "index";
}
}
look it at here.
看看这里。
回答by aviad
BooleanBuilder is good. You can also wrap it and add "optional" methods in order to avoid the if conditions:
BooleanBuilder 很好。您还可以包装它并添加“可选”方法以避免 if 条件:
For example, for "and" you can write: (Java 8 lambdas are used)
例如,对于“and”,您可以编写:(使用 Java 8 lambdas)
public class WhereClauseBuilder implements Predicate, Cloneable
{
private BooleanBuilder delegate;
public WhereClauseBuilder()
{
this.delegate = new BooleanBuilder();
}
public WhereClauseBuilder(Predicate pPredicate)
{
this.delegate = new BooleanBuilder(pPredicate);
}
public WhereClauseBuilder and(Predicate right)
{
return new WhereClauseBuilder(delegate.and(right));
}
public <V> WhereClauseBuilder optionalAnd(@Nullable V pValue, LazyBooleanExpression pBooleanExpression)
{
return applyIfNotNull(pValue, this::and, pBooleanExpression);
}
private <V> WhereClauseBuilder applyIfNotNull(@Nullable V pValue, Function<Predicate, WhereClauseBuilder> pFunction, LazyBooleanExpression pBooleanExpression)
{
if (pValue != null)
{
return new WhereClauseBuilder(pFunction.apply(pBooleanExpression.get()));
}
return this;
}
}
@FunctionalInterface
public interface LazyBooleanExpression
{
BooleanExpression get();
}
And then the usage would be much cleaner:
然后使用会更干净:
public EmployeeEntity getEmployees(String firstName, String lastName) {
QEmployeeEntity employee = QEmployeeEntity.employeeEntity;
return empployeeDAO.findAll
(
new WhereClauseBuilder()
.optionalAnd(firstName, () -> employee.firstName.eq(firstName))
.optionalAnd(lastName, () -> employee.lastName.eq(lastName))
);
}
It is possible also to use jdk's Optional class
也可以使用 jdk 的 Optional 类
回答by MK-rou
This is a very simple way to deal with optional parameters, I use it in my project :
这是处理可选参数的一种非常简单的方法,我在我的项目中使用它:
public List<ResultEntity> findByOptionalsParams(String param1, Integer param2) {
QResultEntity qResultEntity = QResultEntity.resultEntity;
final JPQLQuery<ResultEntity> query = from(qResultEntity);
if (!StringUtils.isEmpty(param1)) {
query.where(qResultEntity.field1.like(Expressions.asString("%").concat(param1).concat("%")));
}
if (param2 != null) {
query.where(qResultEntity.field2.eq(param2));
}
return query.fetch();
}
回答by Jin Kwon
I faced same problem and here comes another version of Timo Westk?mper
's accepted answerusing the Optional
.
我面临着同样的问题,在这里谈到的另一个版本蒂莫Westk?MPER
的公认的答案使用Optional
。
default Optional<Correlation> findOne(
@Nonnull final String value, @Nullable final String environment,
@Nullable final String application, @Nullable final String service) {
final QSome Some = QSome.some;
final BooleanBuilder builder = new BooleanBuilder();
ofNullable(service).map(some.service::eq).map(builder::and);
ofNullable(application).map(some.application::eq).map(builder::and);
ofNullable(environment).map(some.environment::eq).map(builder::and);
builder.and(some.value.eq(value));
return findOne(builder);
}
回答by Roland Schneider
There is another way using Optional
without BooleanBuilder
although the resulting query might be a bit verbose:
尽管结果查询可能有点冗长,但还有另一种使用Optional
without 的方法BooleanBuilder
:
public EmployeeEntity getEmployees(String firstName, String lastName) {
QEmployeeEntity employee = QEmployeeEntity.employeeEntity;
BooleanExpression where = ofNullable(firstName).map(employee.firstName::eq).orElse(Expressions.TRUE)
.and(ofNullable(lastName).map(employee.lastName::eq).orElse(Expressions.TRUE));
return empployeeDAO.findAll(where);
}
Taking that idea and adding a helper function improves readability though:
考虑到这个想法并添加一个辅助函数可以提高可读性:
public EmployeeEntity getEmployees(String firstName, String lastName) {
QEmployeeEntity employee = QEmployeeEntity.employeeEntity;
BooleanExpression where = optionalExpression(firstName, employee.firstName::eq)
.and(optionalExpression(lastName, employee.lastName::eq));
return empployeeDAO.findAll(where);
}
public static <T> BooleanExpression optionalExpression(T arg, Function<T, BooleanExpression> expressionFunction) {
if (arg == null) {
return Expressions.TRUE;
}
return expressionFunction.apply(arg);
}