Hibernate Java

Hibernate – Update an Existing Record

Hibernate – Update an Existing Record

Updating a record in Hibernate is a two-step operation: first load the entity by its primary key, then modify the fields and either let Hibernate auto-detect the change (dirty checking) or call session.merge()/session.update() explicitly. This tutorial shows both approaches with a complete working example.

Prerequisites

  • Java 8 or later
  • Hibernate 5.x
  • MySQL database
  • Maven project

Database Table

CREATE TABLE product (
  id          INT          NOT NULL AUTO_INCREMENT,
  name        VARCHAR(45)  DEFAULT NULL,
  price       DECIMAL(10,0) DEFAULT NULL,
  quantity    INT          DEFAULT NULL,
  description VARCHAR(450) DEFAULT NULL,
  active      TINYINT(1)   DEFAULT NULL,
  created_at  DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id)
);

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/java9rdb</property>
    <property name="connection.username">root</property>
    <property name="connection.password">yourpassword</property>
    <property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>
    <property name="show_sql">true</property>
    <property name="hbm2ddl.auto">update</property>
    <mapping class="com.java9r.model.Product"/>
  </session-factory>
</hibernate-configuration>

Product Entity

package com.java9r.model;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "product")
public class Product {

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

    @Column(name = "name", length = 45)
    private String name;

    @Column(name = "price")
    private Long price;

    @Column(name = "quantity")
    private Integer quantity;

    @Column(name = "description", length = 450)
    private String description;

    @Column(name = "active")
    private Boolean active;

    @Column(name = "created_at")
    private LocalDateTime createdAt;

    public Product() {}

    // Getters
    public Integer       getId()          { return id; }
    public String        getName()        { return name; }
    public Long          getPrice()       { return price; }
    public Integer       getQuantity()    { return quantity; }
    public String        getDescription() { return description; }
    public Boolean       getActive()      { return active; }

    // Setters
    public void setName(String name)               { this.name = name; }
    public void setPrice(Long price)               { this.price = price; }
    public void setQuantity(Integer quantity)       { this.quantity = quantity; }
    public void setDescription(String description) { this.description = description; }
    public void setActive(Boolean active)           { this.active = active; }

    @Override
    public String toString() {
        return String.format("Product{id=%d, name='%s', price=%d, qty=%d}",
                             id, name, price, quantity);
    }
}

HibernateUtil

package com.java9r.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory =
            new Configuration().configure().buildSessionFactory();

    public static SessionFactory getSessionFactory() { return sessionFactory; }
    public static void shutdown()                    { sessionFactory.close(); }
}

ProductDAO – Update Approaches

package com.java9r.dao;

import com.java9r.model.Product;
import com.java9r.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class ProductDAO {

    // ------------------------------------------------------------------
    // Approach 1: Load inside the same session — dirty checking handles
    // the UPDATE automatically on commit, no explicit update() call needed
    // ------------------------------------------------------------------
    public void updateInsideSameSession(Integer id, String newName, Long newPrice) {
        Transaction tx = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            tx = session.beginTransaction();

            Product p = session.get(Product.class, id);
            if (p == null) {
                System.out.println("Product not found: " + id);
                return;
            }
            // Just change the fields — Hibernate detects the change and issues UPDATE
            p.setName(newName);
            p.setPrice(newPrice);

            tx.commit();     // UPDATE SQL runs here automatically
            System.out.println("Updated (dirty check): " + p);
        } catch (Exception e) {
            if (tx != null) tx.rollback();
            throw e;
        }
    }

    // ------------------------------------------------------------------
    // Approach 2: Detached entity — use session.merge() to re-attach and
    // update a Product object that was loaded in a different session
    // ------------------------------------------------------------------
    public void updateDetachedEntity(Product detachedProduct) {
        Transaction tx = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            tx = session.beginTransaction();
            Product merged = session.merge(detachedProduct); // re-attaches + issues UPDATE
            tx.commit();
            System.out.println("Updated (merge): " + merged);
        } catch (Exception e) {
            if (tx != null) tx.rollback();
            throw e;
        }
    }

    // ------------------------------------------------------------------
    // Approach 3: HQL UPDATE — batch-update without loading the entity
    // ------------------------------------------------------------------
    public int updatePriceByHQL(Integer id, Long newPrice) {
        Transaction tx = null;
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            tx = session.beginTransaction();
            int rows = session.createQuery(
                    "UPDATE Product SET price = :price WHERE id = :id")
                .setParameter("price", newPrice)
                .setParameter("id", id)
                .executeUpdate();
            tx.commit();
            System.out.println("Rows updated: " + rows);
            return rows;
        } catch (Exception e) {
            if (tx != null) tx.rollback();
            throw e;
        }
    }

    // Helper: load a product (returns detached after session closes)
    public Product findById(Integer id) {
        try (Session session = HibernateUtil.getSessionFactory().openSession()) {
            return session.get(Product.class, id);
        }
    }
}

Main Class

package com.java9r;

import com.java9r.dao.ProductDAO;
import com.java9r.model.Product;
import com.java9r.util.HibernateUtil;

public class UpdateProductMain {

    public static void main(String[] args) {
        ProductDAO dao = new ProductDAO();

        // Approach 1: update inside same session using dirty checking
        dao.updateInsideSameSession(1, "Gaming Mouse", 2500L);

        // Approach 2: load, detach, modify, re-attach with merge
        Product p = dao.findById(2);     // loaded in one session (now detached)
        p.setDescription("Updated description");
        p.setQuantity(100);
        dao.updateDetachedEntity(p);     // merged in a new session

        // Approach 3: HQL bulk update
        dao.updatePriceByHQL(3, 3000L);

        HibernateUtil.shutdown();
    }
}

Expected Output

Hibernate: select ... from product where id=?
Hibernate: update product set name=?, price=? where id=?
Updated (dirty check): Product{id=1, name='Gaming Mouse', price=2500, qty=50}

Hibernate: select ... from product where id=?
Hibernate: update product set description=?, quantity=? where id=?
Updated (merge): Product{id=2, name='Smartphone', price=25000, qty=100}

Hibernate: update product set price=? where id=?
Rows updated: 1

Choosing the Right Update Approach

Approach Entity State Loads Entity First? Best For
Dirty Checking Persistent (managed) Yes Single record, UI edit flows
session.merge() Detached Yes (SQL SELECT first) REST APIs passing DTOs back
HQL UPDATE Not loaded No Bulk updates, performance-critical paths

Summary

Hibernate provides three ways to update a record. The simplest is to load the entity in an open session and change its fields — Hibernate's dirty-checking mechanism detects the changes and issues the UPDATE on commit. Use session.merge() when the entity was loaded in a different session (detached state). Use HQL bulk updates when you need to update many rows without loading them into memory. Always wrap updates in a transaction and roll back on error.

Topics: Hibernate Java
← Newer Post Older Post →