Welcome back to our Hibernate series! In today’s post, we will explore the Hibernate Criteria API, a powerful and flexible way to perform dynamic and type-safe queries against your entities. This approach is particularly useful when you need to build complex queries programmatically.
What is the Criteria API?
The Criteria API provides a way to create queries using Java code rather than string-based HQL. It allows for a more object-oriented approach to building queries. The Criteria API enhances type safety while also enabling you to create queries dynamically at runtime.
Setting Up Criteria Queries
To get started, ensure your Hibernate setup is ready. Assuming you have a basic entity like Product
, let’s see how to perform criteria queries on it.
First, let’s define our Product
entity:
import javax.persistence.*;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Double price;
// Getters and setters
}
Creating a Criteria Query
To create a criteria query, you start with obtaining a Session
and then use the CriteriaBuilder
to construct your query:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.List;
public class ProductService {
private SessionFactory sessionFactory;
public List<Product> getAllProducts() {
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
List<Product> products;
try {
// Create CriteriaBuilder
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
// Create CriteriaQuery
CriteriaQuery<Product> criteriaQuery = criteriaBuilder.createQuery(Product.class);
// Define the root of the query (entity)
Root<Product> root = criteriaQuery.from(Product.class);
// Query all products
criteriaQuery.select(root);
// Execute query
products = session.createQuery(criteriaQuery).getResultList();
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
} finally {
session.close();
}
return products;
}
}
In this example:
- We use
CriteriaBuilder
to build queries in a type-safe manner. - The root of the query (
Root<Product> root
) is defined based on theProduct
entity. - We create a
CriteriaQuery
that selects all products. - Finally, we execute the query and retrieve the results.
Adding Conditions to Criteria Queries
You can add conditions to filter results based on specific criteria. For example, let’s retrieve products with a price greater than a specified amount:
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
public List<Product> getProductsByMinPrice(Double minPrice) {
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
List<Product> products;
try {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<Product> criteriaQuery = criteriaBuilder.createQuery(Product.class);
Root<Product> root = criteriaQuery.from(Product.class);
// Adding the 'greater than' condition
Predicate pricePredicate = criteriaBuilder.greaterThan(root.get("price"), minPrice);
criteriaQuery.select(root).where(pricePredicate);
products = session.createQuery(criteriaQuery).getResultList();
transaction.commit();
} catch (Exception e) {
transaction.rollback();
throw e;
} finally {
session.close();
}
return products;
}
Here, we are introducing a Predicate
which acts as a condition. The greaterThan
method creates a condition for querying products whose price exceeds minPrice
.
Sorting Results
You can also add sorting to your criteria queries. Here’s how to order products by name:
criteriaQuery.select(root).orderBy(criteriaBuilder.asc(root.get("name")));
Simply add this line before executing the query to sort the results by the product name in ascending order.
Combining Criteria Queries
If you need to combine multiple conditions, use the CriteriaBuilder
to create more complex predicates:
Predicate pricePredicate = criteriaBuilder.greaterThan(root.get("price"), minPrice);
Predicate namePredicate = criteriaBuilder.like(root.get("name"), "%Laptop%");
criteriaQuery.select(root).where(criteriaBuilder.and(pricePredicate, namePredicate));
In this code, we combine two predicates – one for price and one for product name – in a single criteria query.
Conclusion
In this post, we introduced the Hibernate Criteria API, showcasing how to create dynamic and type-safe queries. We explored how to set up criteria queries, add conditions, sort results, and combine queries easily.
Utilizing the Criteria API can significantly enhance the flexibility and maintainability of your data access layer, especially when dealing with complex queries. Experiment with these concepts to strengthen your Hibernate knowledge and usage!
To learn more about ITER Academy, visit our website: ITER Academy.