Necesito crear un JPA dinámico "real" CriteriaBuilder
. Obtengo un Map<String, String>
con las declaraciones. Parece que:JPA CriteriaBuilder realmente dinámico
name : John
surname : Smith
email : [email protected]
...more pairs possible
Esto es lo que implementar:
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)
}
Me trataron de construir un gran Predicate
, que contiene todos los demás predicados y añadir esto a la query.where()
, pero de nuevo los predicados sobreescribe edad valores. Parece que no hay ninguna posibilidad de añadir una Predicate
en lugar de cambio de un predicado :-(
El proyecto real es aún más complicado, debido a que algunos pares requiere una equal
y algunos otros un like
Y eso no es aún lo suficientemente:. Hay podría una declaración adicional con or
incluido como type : 1;4;7
Aquí tiene el valor para dividir y crear una declaración como:.
<rest of statement> AND (type = 1 OR type = 4 OR type = 7)
UPDATE y SOLUCIÓN consiguió dos listas, la primera lista para Y funciona bien. Segunda lista contiene o frases como 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();
Bien, para mis declaraciones AND que funcionan. Creo una segunda lista y almacené mis declaraciones OR en esa lista. Al final, ¿qué hago? Copie ambos resultados de la lista en AND para ambos tipos de declaraciones. Mi lista 'orPredicates' contiene los elementos correctos. Incluso cuando solo agrego esta lista a la consulta, todas las declaraciones se juntan con AND. – Felix
Puede crear una disyunción (o) de la misma manera que crea una conjunción (y) - llamando a los métodos 'o' y' y' en el CriteriaBuilder. El retorno es un solo 'Predicado' en ambos casos, así que si no tienes algún tipo de agrupación compleja, simplemente llama a' y' en los dos Predicados resultantes y usa el resultado en 'where' – kostja
Tal vez lo obtuve ahora, actualicé la pregunta principal y publiqué mi solución. – Felix