我试图为我的Java Web应用程序实现某种数据过滤机会。 在我的情况下,用户应该能够过滤客户 - 例如,在12月2日之后出生并且拥有clientSate ACTIVE或INCATIVE的客户。 在我的例子中,ACTIVE和INACTIVE是枚举值。
由于用户可以选择2或3甚至5种不同的状态,我这样做:
for (EnumValue enumValue : constraint.getValues().getEnumValue()) {
ClientState state = ClientState.valueOf(enumValue.getValue());
predicate = builder.or(builder.equal(client.get(constraint.getField().getValue()), state));
}
但它没有用。
这是我的完整功能代码:
public List<Client> getClients(List<FilterConstraint> filters) {
try {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<?> mainQuery = builder.createQuery(Client.class);
Root<Client> client = mainQuery.from(Client.class);
Predicate predicate = builder.conjunction();
for (FilterConstraint constraint : filters) {
switch (constraint.getOperator()) {
case AFTER:
predicate = builder.and(builder.greaterThan(client.get(constraint.getField().getValue()), constraint.getValues().getStartDate()));
break;
case BEFORE:
predicate = builder.and(builder.greaterThan(client.get(constraint.getField().getValue()), constraint.getValues().getStartDate()));
break;
case BETWEEN:
if (constraint.getField().getType() == FieldDataType.DATE) {
predicate = builder.and(builder.between(client.get(constraint.getField().getValue()), constraint.getValues().getStartDate(), constraint.getValues().getEndDate()));
} else {
predicate = builder.and(builder.between(client.get(constraint.getField().getValue()), constraint.getValues().getMinValue(), constraint.getValues().getMaxValue()));
}
break;
case EMPTY:
predicate = builder.and(builder.isEmpty(client.get(constraint.getField().getValue())));
break;
case EQUALS:
if (constraint.getField().getType() == FieldDataType.ENUM) {
if (constraint.getValues().getEnumValue().size() > 1) {
for (EnumValue enumValue : constraint.getValues().getEnumValue()) {
ClientState state = ClientState.valueOf(enumValue.getValue());
predicate = builder.or(builder.equal(client.get(constraint.getField().getValue()), state));
}
break;
}
ClientState state = ClientState.valueOf(constraint.getValues().getEnumValue().get(0).getValue());
predicate = builder.or(builder.equal(client.get(constraint.getField().getValue()), state));
break;
}
predicate = builder.and(builder.equal(client.get(constraint.getField().getValue()), constraint.getValues().getValue()));
break;
case LESS_THAN:
case MORE_THAN:
case NOT_EMPTY:
case ON:
case STARTS_WITH:
case TODAY:
}
}
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
cq.select(builder.count(cq.from(Client.class)));
em.createQuery(cq);
cq.where(predicate);
Long count = em.createQuery(cq).getSingleResult();
mainQuery.where(predicate);
//TODO Pagination Result should be returned
TypedQuery<?> q = em.createQuery(mainQuery);
List<Client> allClients = (List<Client>) q.getResultList();
return allClients;
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
我搜索了很多,并且无法为OR运算符没有确切值的示例提供资金 - 实际上我发现比较2个值或3个 - 而不是更多。
有人能告诉我如何修复我的代码才能在OR表达式中支持任意数量的值?
答案 0 :(得分:1)
CriteriaBuilder.or
接受谓词数组。因此,只需创建一个“等于枚举值”谓词的数组,并调用该数组的or
一次。
或者,您可能需要考虑in <enum values>
。
答案 1 :(得分:0)
if (constraint.getValues().getEnumValue().size() > 1) {
List<Predicate> predicates = new ArrayList<>();
for (EnumValue enumValue : constraint.getValues().getEnumValue()) {
ClientState state = ClientState.valueOf(enumValue.getValue()); predicates.add(builder.equal(client.get(constraint.getField().getValue()), state));
}
predicate = builder.or(predicates.toArray(new Predicate[]{}));
break;
}
此代码应该适合您