Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic JPA 2.0 query using Criteria API

I am a bit stucked constructing a dynamic query using the CriteriaBuilder of JPA 2.0.

I have quite a common use case I guess: User supplies a arbitrary amount of search parameters X to be and / or concatenated: like :

select e from Foo where (name = X1 or name = X2 .. or name = Xn )

The Method or of CriteriaBuilder is not dynamic:

Predicate or(Predicate... restrictions)

Ideas? Samples?

like image 323
Ben Avatar asked Mar 24 '10 17:03

Ben


People also ask

How use JPA Criteria API?

Let's see it step by step: Create an instance of Session from the SessionFactory object. Create an instance of CriteriaBuilder by calling the getCriteriaBuilder() method. Create an instance of CriteriaQuery by calling the CriteriaBuilder createQuery() method.

Why do we need JPA Criteria API?

Java Prime Pack The Criteria API is a predefined API used to define queries for entities. It is the alternative way of defining a JPQL query. These queries are type-safe, and portable and easy to modify by changing the syntax. Similar to JPQL it follows abstract schema (easy to edit schema) and embedded objects.

What is root in Criteria API?

For a particular CriteriaQuery object, the root entity of the query, from which all navigation originates, is called the query root. It is similar to the FROM clause in a JPQL query. Create the query root by calling the from method on the CriteriaQuery instance.

What is CriteriaBuilder in Java?

public interface CriteriaBuilder. Used to construct criteria queries, compound selections, expressions, predicates, orderings. Note that Predicate is used instead of Expression<Boolean> in this API in order to work around the fact that Java generics are not compatible with varags. Since: Java Persistence 2.0.


2 Answers

In your case, I would rather use Expression#in(Collection) to avoid having to loop and to build a compound Predicate dynamically:

CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Foo> cq = cb.createQuery(Foo.class);
Metamodel m = em.getMetamodel();
EntityType<Foo> Foo_ = m.entity(Foo.class);
Root<Foo> foo = cq.from(Foo_);
cq.where(my.get(Foo_.name).in(params));

You might want to check Basic Type-Safe Queries Using the Criteria API and Metamodel API for more details.

like image 135
Pascal Thivent Avatar answered Oct 10 '22 16:10

Pascal Thivent


in this code Foo_.name is going to give compilation error. As the field is not declared in that. I'm not able to understand this. Please suggest me.

-raghu

like image 21
raghunath Avatar answered Oct 10 '22 15:10

raghunath