Domanda

Need to generate a query like so using JPA. It needs to be dynamic because I don't know till runtime what parameters I'd get.

SQL I'd like from JPA:

select * from foo where a='A' OR b='B' OR c='C' OR (x='X' AND y='Y')

  • Don't know ahead of time if any of 'A', 'B', 'C', 'X', 'Y' will be provided.
  • X and Y should always use 'AND'.
  • If one of the inputs is missing, example, if C is not provided, we should simply eliminate that - query becomes - "select * from foo where a='A' OR b='B' OR (x='X' AND y='Y')

Most of the examples I've come across using JPA are simply using the AND operator when a query is dynamically generated. Either that, or, they are doing it statically using "criteriabuilder.or(..., ..., ...). That won't work in my case.

È stato utile?

Soluzione

You can use either CriteriaBilder#disjunction() operator in order to build a Predicate to be dynamically modified:

Integer aValue, xValue, yValue;
Predicate p = cb.disjunction();
if (aValue != null) {
    p = cb.or(p, cb.equal(foo.get("a"), aValue));
}
...
if (xValue != null && yValue != null) {
    p = cb.or(p, cb.and(cb.equal(foo.get("x"), xValue), cb.equal(foo.get("y"), yValue)));
}

Or use an array of predicates:

List<Predicate> predicateArray = new ArrayList<> ();
if (aValue != null) {
    predicateArray.add(cb.equal(foo.get("a"), aValue));
}
...
if (xValue != null && yValue != null) {
    predicateArray.add(cb.and(cb.equal(foo.get("x"), xValue), cb.equal(foo.get("y"), yValue)));
}
Predicate p = cb.or(predicateArray.toArray(new Predicate[] {})));

Altri suggerimenti

You can write your query storing that in a String variable where you can append several parts of that respect some condition.

An example:

// This part is always presents
String hql = " SELECT * FROM foo ";
String whereClause = " where ";
String whereCond = "";

if (condition on A is satisfacted) {
    whereCond += "a = 'A'";
}

if (condition on B is satisfacted) {
    if (!whereCond.equals("")) {
        whereCond += " or ";
    }
    whereCond += "b = 'B'";
}

... AND GO ON ...

At the end

String res = hql;
if (!whereCond.equals("")) {
   res += whereClause + whereCond;
}

return res;

Tell me if it's OK

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top