Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional where clause in JPA criteria query

I am facing an issue for JPA criteria query. How can I add multiple where clause in my Criteria Query with if else...

My Requirement is:

CriteriaBuilder builder = getEm().getCriteriaBuilder();
CriteriaQuery<Object> query = builder.createQuery(Object.class);

// From
Root<EntityClass> entity= query.from(EntityClass.class);
// Select
query.multiselect(entity.get("id").get("col1"),entity.get("id").get("col2"));
// Where
Predicate p1 = builder.and(builder.equal(entity.get("col3"), value3));
Predicate p2 = builder.and(builder.equal(entity.get("col4"), value4));
Predicate p3 = builder.and(builder.equal(entity.get("col5"), value5));
if(someCondition1){
    query.where(p1);
}else if(someCondition2){
    query.where(p1);
}
query.where(p3);

In above code the statement query.where(p3); replaces previously set where clause condition p1 and p2. What the alternate I found is conjunct like below

if(someCondition1){
    query.where(p1, p3);
}else if(someCondition2){
    query.where(p2, p3);
}else{
    query.where(p3);
}

But that is not a good approach, because when there are many if-else this becomes very bad to write repeating codes. Can any one have a solution for this?

like image 945
gahlot.jaggs Avatar asked Dec 31 '12 05:12

gahlot.jaggs


People also ask

What is CriteriaBuilder in JPA?

EntityManager instance is used to create a CriteriaBuilder object. CriteriaQuery instance is used to create a query object. This query object's attributes will be modified with the details of the query. CriteriaQuery. from method is called to set the query root.

Is Criteria API deprecated?

The Criteria API allows us to build up a criteria query object programmatically, where we can apply different kinds of filtration rules and logical conditions. Since Hibernate 5.2, the Hibernate Criteria API is deprecated, and new development is focused on the JPA Criteria API.


2 Answers

You can create a Predicate array to store your conditional Predicates and then add it to the WHERE clause:

List<Predicate> predList = new LinkedList<Predicate>();
if (someCondition1) {
    predList.add(p1);
} else if (someCondition2) {
    predList.add(p2);
}
predList.add(p3);
Predicate[] predArray = new Predicate[predList.size()];
predList.toArray(predArray);
query.where(predArray);

This allows to dynamically add any kind of predicate.

like image 104
jmendiola Avatar answered Nov 06 '22 11:11

jmendiola


Something like this:

Predicate p;
Predicate p3 = builder.equal(entity.get("col5"), value5);
if(someCondition1){
    p = builder.equal(entity.get("col3"), value3);
}else if(someCondition2){
    p = builder.equal(entity.get("col4"), value4);
}
if (p != null) p = builder.and(p, p3);
else p = p3;
query.where(p);

So don't call where in every if just build a complete expression and call where once at the end.

like image 31
Eelke Avatar answered Nov 06 '22 11:11

Eelke