What is the difference between JPQL and Criteria API?
In Java Persistence API (JPA), both JPQL (JPA Query Language) and the Criteria API serve as powerful mechanisms to query data from a persistent store. While both achieve the same goal of retrieving or manipulating entities, they approach query construction and execution in fundamentally different ways.
JPQL (JPA Query Language)
JPQL is a platform-independent, object-oriented query language used in JPA. It is syntactically similar to SQL but operates on entity objects and their relationships rather than database tables and columns. JPQL queries are typically written as strings and parsed at runtime.
SELECT p FROM Product p WHERE p.price > :minPrice
JPA Criteria API
The JPA Criteria API provides a programmatic way to construct queries using Java objects and methods. It allows developers to build queries dynamically and leverage the type safety provided by the Java compiler, eliminating many common runtime errors associated with string-based queries.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Product> cq = cb.createQuery(Product.class);
Root<Product> product = cq.from(Product.class);
cq.select(product).where(cb.greaterThan(product.get("price"), minPrice));
TypedQuery<Product> query = entityManager.createQuery(cq);
List<Product> products = query.getResultList();
Key Differences
| Feature | JPQL | Criteria API |
|---|---|---|
| Nature | String-based | Programmatic, object-based |
| Syntax | SQL-like, easy to read for static queries | Java method calls, can be verbose for simple queries |
| Type Safety | Runtime errors for typos (e.g., entity/field names) | Compile-time safety (IDE validation, prevents typos) |
| Dynamic Queries | Complex to build dynamically (string concatenation, conditional logic) | Easier and safer to build dynamic queries with predicates |
| Refactoring | Limited IDE support; relies on search-and-replace for entity/field names | Full IDE refactoring support, changes cascade automatically |
| Readability | Often more readable for simple, static queries | Can be less readable for simple queries, but structured for complex ones |
| Portability | Highly portable across different JPA providers | Highly portable across different JPA providers |
| Learning Curve | Generally lower for those familiar with SQL | Higher initially, requires understanding of builder patterns |
When to Use Which?
- When queries are static and known at design time.
- For simple to moderately complex queries where readability is prioritized.
- When quick development and SQL-like syntax are preferred.
- If you are already familiar with SQL and prefer a similar query style.
- When queries need to be built dynamically based on varying user input or conditions.
- For complex queries with many optional predicates or joins.
- When compile-time type safety is paramount to prevent runtime errors.
- When extensive refactoring support is desired, as changes to entity fields are caught by the compiler.
In practice, many applications utilize both JPQL and the Criteria API, choosing the appropriate tool based on the specific requirements of each query. JPQL often handles the common, static queries, while the Criteria API is reserved for highly dynamic or exceptionally complex scenarios.