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.


Updating Objects with Hibernate

Hibernate provides several ways to update existing objects in the database. The primary methods are using session.update() and directly modifying persistent objects within a transaction. Understanding detached objects and reattachment is also crucial.

1. Updating using session.update()

The session.update() method is used to update a detached object in the database. An object is considered detached when it's no longer associated with a Hibernate session. Typically, this happens after a session is closed or the object is retrieved in one session and updated in another.

Here's the process:

  1. Retrieve the object from the database in one session.
  2. Close the session (or otherwise detach the object).
  3. Modify the detached object.
  4. Open a new session.
  5. Call session.update(detachedObject) to re-attach and update the object.
  6. Commit the transaction.

Example:

 // Assume 'Employee' is a mapped entity class

// Step 1 & 2: Retrieve and Detach
Session session1 = sessionFactory.openSession();
Transaction tx1 = session1.beginTransaction();
Employee employee = session1.get(Employee.class, 1L); // Retrieve employee with ID 1
tx1.commit();
session1.close();

// At this point, 'employee' is a detached object

// Step 3: Modify
employee.setSalary(60000.0);

// Step 4, 5 & 6: Re-attach and Update
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
session2.update(employee); // Re-attach and schedule for update
tx2.commit();
session2.close(); 

Important Considerations for session.update():

  • The object's ID (primary key) must exist in the database. If an object with that ID does not exist, Hibernate will throw an exception (usually a NonUniqueObjectException or similar, depending on configuration and caching).
  • session.update() merges the state of the detached object into the persistent object. Any changes made to the detached object *after* it was detached from the *first* session will be reflected in the database.

2. Modifying Persistent Objects within a Transaction

This is the simplest and often preferred method for updating objects. When an object is retrieved within a transaction, it becomes a persistent object managed by Hibernate. Any changes made to this object during the transaction will be automatically synchronized with the database when the transaction is committed. This is because of Hibernate's dirty checking mechanism.

Here's the process:

  1. Open a session and begin a transaction.
  2. Retrieve the object from the database using session.get() or session.load().
  3. Modify the object's properties.
  4. Commit the transaction. Hibernate automatically detects the changes and updates the database.

Example:

 // Assume 'Employee' is a mapped entity class

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

Employee employee = session.get(Employee.class, 1L); // Retrieve employee with ID 1

if (employee != null) {
    employee.setSalary(60000.0);  // Modify the salary
}

tx.commit(); // Hibernate will automatically update the database
session.close(); 

Important Considerations for Persistent Object Modification:

  • Hibernate's dirty checking automatically detects changes. You don't need to explicitly call an update method.
  • Changes are synchronized at transaction commit. Ensure the transaction is committed to persist the changes.
  • It is crucial to retrieve the object within a transaction to make it a persistent object.
  • Be mindful of long transactions. The longer a transaction is open, the higher the risk of conflicts and performance issues.

3. Detached Objects and Reattachment

A detached object is an instance of a persistent class that was once associated with a Hibernate session but is no longer associated. This typically happens when a session is closed or when the object is explicitly detached.

Reattachment is the process of re-associating a detached object with a new Hibernate session. This is necessary when you want to update a detached object's state in the database.

Hibernate offers several ways to reattach a detached object:

  • session.update(detachedObject): As described above, this method copies the state of the detached object into the persistent object with the same identifier. The detached object's state becomes the persistent object's new state.
  • session.merge(detachedObject): This method creates a *new* persistent instance and copies the state of the detached object to the newly created object. The detached object remains detached. This is generally preferred when you are unsure if an object with the same identifier exists or if the object has been changed elsewhere. It avoids potential NonUniqueObjectException.
  • session.lock(detachedObject, LockMode.NONE): This re-associates the detached object with the session, but does *not* update the database immediately. It allows you to then make further changes to the object within the current session before committing the transaction. This should be avoided when using automatic dirty checking; it is more applicable when using manual flushing strategies.
  • Retrieving the object in a new session, setting all properties of the retrieved entity with the data from the detached object, and saving that newly populated object. This requires all properties to be copied and can be error-prone if properties are added later on.

Key Differences between update() and merge():

Featuresession.update()session.merge()
AssociationRe-associates the detached object with the session.Does *not* re-associate the detached object. Creates a *new* persistent instance.
Object StateThe detached object's state is copied to a persistent object.The detached object's state is copied to a *new* persistent object.
Detached ObjectBecomes associated with the new sessionRemains detached.
When to UseWhen you are sure that an object with the same ID exists and want to update it.When you are *not* sure if an object with the same ID exists, or when you want to update it using an external datasource.
Exception RiskCan throw NonUniqueObjectException if an object with the same ID does not exist.Less likely to throw NonUniqueObjectException because it always creates a new instance or overwrites existing data with the provided data.

Choosing the correct method depends on your specific use case and data integrity requirements.

In Summary, hibernate provides versatile methods for updating objects. When using detached objects use caution with session.update() because of the non-unique object exception and consider using session.merge() which helps avoid this issue. For a simpler approach when the object remains within the session, modifying a persistent object inside of a transaction makes the update operation more manageable.