Tôi cần tạo một JPA động "thực" động CriteriaBuilder
. Tôi nhận được một số Map<String, String>
với các câu lệnh. Dường như:Tiêu chí JPA thực sự năng độngBuilder
name : John
surname : Smith
email : [email protected]
...more pairs possible
Dưới đây là những gì tôi thực hiện:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> userRoot = query.from(User.class);
query.select(userRoot);
List<Predicate> predicates = new ArrayList<Predicate>();
Iterator<String> 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)
}
Tôi cố gắng để xây dựng một lớn Predicate
, trong đó có tất cả các vị từ khác và thêm video này vào các query.where()
, nhưng một lần nữa các vị từ ghi đè cũ giá trị. Hình như không có khả năng để thêm một Predicate
thay vì thay đổi một Predicate :-(
Dự án thực thậm chí còn phức tạp hơn, bởi vì một số cặp yêu cầu một equal
và một số khác một like
Và đó là thậm chí không đủ. Có một tuyên bố thêm với or
có thể bao gồm như type : 1;4;7
Ở đây, giá trị phải chia tay và tạo ra một tuyên bố như sau:.
<rest of statement> AND (type = 1 OR type = 4 OR type = 7)
UPDATE và SOLUTION Got hai danh sách, Danh sách đầu tiên cho AND hoạt động tốt. danh sách thứ hai chứa OR như exspected:
final List<Predicate> andPredicates = new ArrayList<Predicate>();
final List<Predicate> orPredicates = new ArrayList<Predicate>();
for (final Entry<String, String> 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.<String> 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();
Được rồi, đối với các câu lệnh AND của tôi hoạt động. Tôi tạo một Danh sách thứ hai và lưu trữ các câu lệnh OR của tôi trong danh sách đó. Cuối cùng, tôi làm gì? Sao chép cả hai kết quả togehter danh sách trong AND cho cả hai loại câu lệnh. Danh sách 'orPredicates' của tôi chứa các phần tử chính xác. Ngay cả khi tôi chỉ thêm danh sách này vào truy vấn, tất cả các câu lệnh được đặt cùng với AND. – Felix
Bạn có thể tạo ra một disjunction (hoặc) giống như cách bạn tạo một kết hợp (và) - bằng cách gọi 'hoặc' và' và 'phương pháp trên CriteriaBuilder. Sự trở lại là một 'Predicate' duy nhất trong cả hai trường hợp - vì vậy nếu bạn không có một số nhóm phức tạp, chỉ cần gọi' và' trên hai kết quả Predicates và sử dụng kết quả trong 'where' – kostja
Có lẽ tôi đã nhận nó ngay bây giờ, tôi đã cập nhật câu hỏi chính và đăng giải pháp của tôi. – Felix