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.
Reading (Retrieving) Objects with Hibernate
Hibernate provides several mechanisms for retrieving objects from the database. The most common methods are session.get()
, session.load()
, and HQL/Criteria queries. Understanding the differences between these methods and how to handle potential exceptions like ObjectNotFoundException
is crucial for effective data retrieval.
Retrieving Objects with session.get()
The session.get()
method retrieves an object from the database based on its primary key. If the object exists, it's returned immediately. If the object does not exist, session.get()
returns null
.
Example:
Session session = sessionFactory.openSession();
try {
Student student = session.get(Student.class, 123); // 123 is the primary key
if (student != null) {
System.out.println("Student Name: " + student.getName());
} else {
System.out.println("Student with ID 123 not found.");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
Explanation:
- The code opens a Hibernate session.
session.get(Student.class, 123)
attempts to retrieve aStudent
object with the primary key123
.- If a
Student
object with that ID exists, it's returned and its name is printed. - If no such
Student
exists,student
will benull
, and a "not found" message is printed. - The session is closed in the
finally
block to ensure proper resource management.
Retrieving Objects with session.load()
The session.load()
method also retrieves an object based on its primary key, but it behaves differently from session.get()
. Instead of immediately hitting the database, session.load()
returns a proxy object. This proxy object only retrieves the data from the database when you actually access one of its properties. If the object does not exist in the database, accessing a property of the proxy object will result in an ObjectNotFoundException
being thrown.
Example:
Session session = sessionFactory.openSession();
try {
Student student = session.load(Student.class, 456); // 456 is the primary key
// No database access yet. 'student' is a proxy object.
System.out.println("Student class: " + student.getClass().getName());
// Database access occurs here, when we try to get the name.
// If student with ID 456 doesn't exist, ObjectNotFoundException will be thrown.
System.out.println("Student Name: " + student.getName());
} catch (ObjectNotFoundException e) {
System.out.println("Student with ID 456 not found (ObjectNotFoundException).");
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
Explanation:
session.load(Student.class, 456)
returns a proxy object representing theStudent
with ID456
. No database query is executed at this point.- The
System.out.println("Student class: " + student.getClass().getName());
will print the proxy class name. - The database is accessed only when
student.getName()
is called. - If the student with ID 456 doesn't exist, an
ObjectNotFoundException
is thrown during thestudent.getName()
call.
Key Differences between get()
and load()
:
get()
returnsnull
if the object isn't found.load()
throws anObjectNotFoundException
when you try to access a property of the proxy object if the object doesn't exist.get()
always hits the database immediately.load()
returns a proxy object and only hits the database when needed (lazy loading).- Use
get()
when you need to check if an object exists immediately. Useload()
when you're certain the object exists, and you want to potentially defer database access for performance reasons.
Retrieving Objects with HQL/Criteria Queries
Hibernate Query Language (HQL) and Criteria queries provide more flexible ways to retrieve data. They allow you to specify complex criteria for selecting objects.
Example (HQL):
Session session = sessionFactory.openSession();
try {
String hql = "FROM Student WHERE name = :studentName";
Query<Student> query = session.createQuery(hql, Student.class);
query.setParameter("studentName", "Alice");
List<Student> students = query.list();
if (!students.isEmpty()) {
for (Student student : students) {
System.out.println("Student ID: " + student.getId() + ", Name: " + student.getName());
}
} else {
System.out.println("No students found with the name 'Alice'.");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
Explanation:
- The code defines an HQL query to retrieve all
Student
objects where thename
property is equal to "Alice". query.setParameter("studentName", "Alice")
sets the value of the named parameter:studentName
in the HQL query. This is best practice to prevent SQL injection.query.list()
executes the query and returns a list ofStudent
objects.- The code iterates through the list and prints the ID and name of each student.
Example (Criteria API):
Session session = sessionFactory.openSession();
try {
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Student> criteria = builder.createQuery(Student.class);
Root<Student> root = criteria.from(Student.class);
criteria.select(root).where(builder.equal(root.get("city"), "New York"));
List<Student> students = session.createQuery(criteria).getResultList();
if (!students.isEmpty()) {
for (Student student : students) {
System.out.println("Student ID: " + student.getId() + ", Name: " + student.getName() + ", City: " + student.getCity());
}
} else {
System.out.println("No students found from 'New York'.");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
Explanation:
- This example shows how to use the Criteria API to build a query to retrieve
Student
objects whosecity
is "New York". - It uses the
CriteriaBuilder
to create aCriteriaQuery
. - The
Root<Student>
represents the root entity in the query (i.e., theStudent
entity). - The
where
clause specifies the filtering criteria. - The
session.createQuery(criteria).getResultList()
executes the query and returns the result as a list ofStudent
objects.
Handling ObjectNotFoundException
The ObjectNotFoundException
is thrown by session.load()
(or when accessing lazy-loaded properties) when an object with the specified ID does not exist in the database. It's important to handle this exception to prevent your application from crashing and to provide a user-friendly error message.
Example (Handling ObjectNotFoundException
):
Session session = sessionFactory.openSession();
try {
Student student = session.load(Student.class, 999); // Assuming 999 is a non-existent ID
//This will cause ObjectNotFoundException
System.out.println("Student Name: " + student.getName());
} catch (ObjectNotFoundException e) {
System.out.println("Error: Student with ID 999 not found.");
// Optionally log the error or take other appropriate action.
} catch (Exception e) {
e.printStackTrace(); // Handle other potential exceptions
} finally {
session.close();
}
Explanation:
- The code attempts to load a
Student
object with the ID999
. - If a student with that ID doesn't exist, accessing
student.getName()
will throw anObjectNotFoundException
. - The
catch (ObjectNotFoundException e)
block catches the exception and prints an informative error message to the console. In a real application, you might log the error or display a user-friendly message on the UI. - The
catch (Exception e)
is a general exception handler to catch any other unexpected exceptions.
Best Practices:
- Choose the appropriate retrieval method (
get()
,load()
, HQL/Criteria) based on your application's requirements. - Handle
ObjectNotFoundException
gracefully, providing informative error messages or taking appropriate action. - Use parameterized queries (with HQL/Criteria) to prevent SQL injection.
- Always close your Hibernate sessions in a
finally
block to ensure resources are released.