我需要创建一个“真实的”动态JPA AND (type = 1 OR type = 4 OR type = 7)。我得到一个带有以下语句的like。 看起来像:
name : John
surname : Smith
email : email@email.de
...more pairs possible
这是我实现的:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(User.class);
Root userRoot = query.from(User.class);
query.select(userRoot);
List predicates = new ArrayList();
Iterator column = statements.keySet().iterator();
while (column.hasNext()) {
// get the pairs
String colIndex = column.next();
String colValue = statements.get(colIndex);
// create the statement
Predicate pAnd = cb.conjunction();
pAnd = cb.and(pAnd, cb.equal(userRoot.get(colIndex), colValue));
predicates.add(pAnd);
}
// doesn't work, i don't know how many predicates i have -> can not address them
query.where(predicates.get(0), predicates.get(1), ...);
// doesn't work, because it is a list of predicates
query.where(predicates);
// doesn't work, because the actual predicate overwrites the old predicate
for (Predicate pre : predicates) {
query.where(pre)
}
我试图建立一个包含所有其他谓词的大29581604750005000328,并将其添加到like,但是这些谓词再次覆盖了旧值。 似乎没有可能添加一个or而不是更改谓词:-(
实际的项目更加复杂,因为有些对需要29581604750005000931328,而另一些对需要like。这还不够:可能有像29581604750005000331331那样包含or的额外语句。在这里,值必须拆分并创建类似 :
AND (type = 1 OR type = 4 OR type = 7)
更新和解决方案得到了两个列表,第一个AND列表很好用。 第二个列表包含OR语句,例如:
final List andPredicates = new ArrayList();
final List orPredicates = new ArrayList();
for (final Entry entry : statements.entrySet()) {
final String colIndex = entry.getKey();
final String colValue = entry.getValue();
if (colIndex != null && colValue != null) {
if (!colValue.contains(";")) {
if (equals) {
andPredicates.add(cb.equal(userRoot.get(colIndex), colValue));
} else {
andPredicates.add(cb.like(userRoot. get(colIndex), "%" + colValue + "%"));
}
} else {
String[] values = colValue.split(";");
for (String value : values) {
orPredicates.add(cb.or(cb.equal(userRoot.get(colIndex), value)));
}
}
}
}
// Here goes the magic to combine both lists
if (andPredicates.size() > 0 && orPredicates.size() == 0) {
// no need to make new predicate, it is already a conjunction
query.where(andPredicates.toArray(new Predicate[andPredicates.size()]));
} else if (andPredicates.size() == 0 && orPredicates.size() > 0) {
// make a disjunction, this part is missing above
Predicate p = cb.disjunction();
p = cb.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
query.where(p);
} else {
// both types of statements combined
Predicate o = cb.and(andPredicates.toArray(new Predicate[andPredicates.size()]));
Predicate p = cb.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
query.where(o, p);
}
query.where(predicates.toArray(new Predicate[predicates.size()]));
users = em.createQuery(query).getResultList();