Hibernate Criteria API vs JPQL

Hibernate Criteria API vs JPQL

Both Hibernate Criteria API and JPQL are used for querying data in a Hibernate/JPA environment, but they differ in how they construct and execute queries.


1. Hibernate Criteria API

The Criteria API is a programmatic way to build queries using Java objects instead of writing JPQL/SQL strings.

Key Features

Type-safe: Uses Java objects and avoids syntax errors in query strings.

Dynamic queries: Easy to build queries dynamically based on conditions.

Object-oriented: Uses entity fields instead of table columns.

Vendor-independent: Works with different databases without modification.

Example

Querying users whose email contains "example@gmail.com" using Criteria API:

@PersistenceContext
private EntityManager entityManager;

public List<User> getUsersByCriteria() {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> root = cq.from(User.class);

cq.select(root).where(cb.like(root.get("email"), "%example@gmail.com%"));

TypedQuery<User> query = entityManager.createQuery(cq);
List<User> users = query.getResultList();
}        

2. JPQL (Java Persistence Query Language)

JPQL is a string-based query language that is similar to SQL but works with entity names and fields instead of table names and columns.

Key Features

Similar to SQL: Easier to learn for those familiar with SQL.

Supports complex queries: Joins, aggregates, subqueries, etc.

More readable for static queries.

Example

Querying users whose email contains "example@gmail.com" using JPQL:

String jpql = "SELECT u FROM User u WHERE u.email LIKE :email";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
query.setParameter("email", "%example@gmail.com%");
List<User> users = query.getResultList();        

or

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.email LIKE %:email%")
    List<User> findByEmailContaining(@Param("email") String email);
}        

Key Differences


Article content

When to Use What?

  • Use JPQL when writing static queries that are easy to understand.
  • Use Criteria API when you need dynamic queries that change based on user input or conditions.


3. Criteria API vs. Native Query in Hibernate: A Comparison

When working with Hibernate and Spring Data JPA, you often need to choose between Criteria API and Native Queries for fetching data dynamically. This article explores both approaches using an example of querying a Frame entity, optionally fetching its associated Category.


Case 1: Using Criteria API for Dynamic Queries

The Criteria API provides a type-safe, object-oriented way to construct queries dynamically. It is useful when query conditions change based on user input.

Scenario

We want to fetch Frame entities, and optionally fetch their associated Category based on a type parameter.

Implementation

    @PersistenceContext
    private EntityManager entityManager;

    public List<Frame> getFramesUsingCriteria(String type) {
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Frame> query = builder.createQuery(Frame.class);
        Root<Frame> root = query.from(Frame.class);

        if ("fetch".equals(type)) {
            root.fetch("category"); // Dynamically fetch category relationship
        }

        query.select(root);
        TypedQuery<Frame> typedQuery = entityManager.createQuery(query);
        return typedQuery.getResultList();
    }
}        

How It Works

  1. CriteriaBuilder is used to create a dynamic query.
  2. Root<Frame> defines the entity being queried.
  3. Conditionally fetches category if the type parameter is "fetch".
  4. Executes the query using entityManager.createQuery().

Pros of Criteria API

Type-safe: Avoids runtime errors due to incorrect query syntax.

Flexible: Allows building dynamic queries without writing raw SQL.

Works across databases: Independent of SQL dialects.

Cons

More verbose than JPQL.

Harder to read and maintain for complex queries.


Case 2: Using Native SQL Query

Sometimes, you need raw SQL queries for performance optimization or when working with database-specific functions. The Native Query approach allows direct execution of SQL statements.

Scenario

We need to retrieve all Frame records and join them with their corresponding Category entities using SQL.

Implementation

    @PersistenceContext
    private EntityManager entityManager;

    public List<Frame> getFramesUsingNativeQuery() {
        return entityManager.createNativeQuery("""
                SELECT e.*
                FROM frames e
                JOIN categories c ON e.category_id = c.id
                """, Frame.class).getResultList();
    }
}
        

How It Works

  1. The createNativeQuery() method executes a raw SQL query.
  2. The SQL query joins frames and categories tables.
  3. Frame.class mapping ensures entity conversion instead of returning raw database results.

Pros of Native Query

Faster execution for complex queries.

Direct SQL control, useful for database-specific optimizations.

Easier for SQL-experienced developers.

Cons

Tightly coupled to database dialects, requiring modifications when switching databases.

No compile-time validation, increasing the risk of runtime errors.


When to Use Which?

Article content

Conclusion

  • Use Criteria API when working with dynamic, object-oriented queries in Hibernate.
  • Use Native Query when performance optimization or database-specific features are needed.


To view or add a comment, sign in

Others also viewed

Explore topics