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();
}
}
}