CRUD Operations with Hibernate (Create, Read, Update, Delete)

This is a hands-on lesson demonstrating how to perform basic CRUD operations using Hibernate. You'll learn how to save new objects to the database (Create), retrieve objects (Read), modify existing objects (Update), and delete objects (Delete) using Hibernate's API.


Hibernate Query Language (HQL)

Introduction to HQL

Hibernate Query Language (HQL) is an object-oriented query language, similar in appearance to SQL, but instead of operating on tables and columns, HQL works with persistent objects and their properties. It provides a way to query the database from a Java application using Hibernate without writing native SQL. HQL is translated by Hibernate into the appropriate SQL dialect for the underlying database.

Key benefits of using HQL:

  • Abstraction: HQL abstracts away the database-specific SQL syntax, making your application more portable.
  • Object-Oriented: It deals with objects and their properties, making queries more readable and maintainable.
  • Type-Safe: Queries are type-checked at compile time (to some extent, based on your IDE and setup), reducing runtime errors.

Understanding HQL

HQL queries resemble SQL but operate on entities and their attributes. Instead of specifying table names, you use the names of your Java classes (entities). Instead of column names, you use the names of the class's attributes.

For example, consider a simple Employee entity:

 @Entity
@Table(name = "employees")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;
    private String lastName;

    private String email;

    // Getters and setters (omitted for brevity)
}

A corresponding HQL query might look like this:

 from Employee 

This query would retrieve all Employee objects from the database.

Writing HQL Queries

Selecting Data

The most common use case for HQL is selecting data. Here are some examples:

Selecting all Employees

  from Employee 

Selecting specific properties

  select e.firstName, e.lastName from Employee e 

Using WHERE clause

  from Employee e where e.email like '%@example.com' 

Using ORDER BY clause

  from Employee e order by e.lastName, e.firstName 

Updating Data

HQL allows you to update data directly through queries.

Updating Employee email

  update Employee set email = 'new.email@example.com' where id = 1 

Deleting Data

HQL provides a way to delete data based on conditions.

Deleting an Employee

  delete Employee where id = 1 

Using Parameters in HQL Queries

Using parameters in HQL queries is crucial for security (preventing SQL injection) and performance (allowing Hibernate to optimize the query plan). There are two main ways to use parameters:

Positional Parameters

Positional parameters are identified by their position in the query, starting from 1.

  from Employee e where e.firstName = ?1 and e.lastName = ?2 

In Java code:

  Query query = session.createQuery("from Employee e where e.firstName = ?1 and e.lastName = ?2");
query.setParameter(1, "John");
query.setParameter(2, "Doe");
List<Employee> employees = query.list(); 

Named Parameters

Named parameters are identified by a name preceded by a colon (:).

  from Employee e where e.firstName = :firstName and e.lastName = :lastName 

In Java code:

  Query query = session.createQuery("from Employee e where e.firstName = :firstName and e.lastName = :lastName");
query.setParameter("firstName", "John");
query.setParameter("lastName", "Doe");
List<Employee> employees = query.list(); 

Recommendation: Named parameters are generally preferred because they are more readable and less prone to errors if the query is modified.

Example: Retrieving Employees by First Name

Here's a complete example of how to retrieve employees by first name using HQL and named parameters:

  import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query; //Use org.hibernate.query.Query for Hibernate 5+

import java.util.List;

public class HQLQueryExample {

    public static void main(String[] args) {
        // Configure Hibernate
        Configuration configuration = new Configuration().configure("hibernate.cfg.xml").addAnnotatedClass(Employee.class);
        SessionFactory sessionFactory = configuration.buildSessionFactory();

        // Open a session
        try (Session session = sessionFactory.openSession()) {
            // Begin a transaction
            session.beginTransaction();

            // HQL query with named parameters
            String hql = "from Employee e where e.firstName = :firstName";
            Query<Employee> query = session.createQuery(hql, Employee.class); // Specify result type
            query.setParameter("firstName", "John");

            // Execute the query
            List<Employee> employees = query.list();

            // Process the results
            for (Employee employee : employees) {
                System.out.println("Employee ID: " + employee.getId());
                System.out.println("Employee Name: " + employee.getFirstName() + " " + employee.getLastName());
                System.out.println("Employee Email: " + employee.getEmail());
                System.out.println("--------------------");
            }

            // Commit the transaction
            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sessionFactory.close();
        }
    }
}