Tutorials Logic, IN info@tutorialslogic.com

Hibernate CRUD save, get, update, delete

Session CRUD Methods

Method Description Returns
session.persist(obj) Insert new entity (JPA standard) void
session.save(obj) Insert new entity (Hibernate legacy) Serializable (ID)
session.get(Class, id) Load entity by ID (returns null if not found) Entity or null
session.load(Class, id) Load proxy by ID (throws exception if not found) Proxy
session.update(obj) Update detached entity void
session.merge(obj) Merge detached entity state (JPA standard) Managed entity
session.delete(obj) Delete entity (Hibernate legacy) void
session.remove(obj) Delete entity (JPA standard) void
session.saveOrUpdate(obj) Insert or update based on ID void

Create and Read Operations

Create and Read Operations
public class UserDAO {
    private SessionFactory sessionFactory;

    public UserDAO(SessionFactory sf) { this.sessionFactory = sf; }

    // CREATE
    public Long createUser(User user) {
        Session session = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            session.persist(user);  // INSERT INTO users ...
            tx.commit();
            return user.getId();
        } catch (Exception e) {
            if (tx != null) tx.rollback();
            throw e;
        } finally {
            session.close();
        }
    }

    // READ by ID - get() returns null if not found
    public User getUserById(Long id) {
        try (Session session = sessionFactory.openSession()) {
            return session.get(User.class, id);
        }
    }

    // READ by ID - load() returns proxy, throws ObjectNotFoundException if not found
    public User getUserProxy(Long id) {
        try (Session session = sessionFactory.openSession()) {
            return session.load(User.class, id); // Lazy proxy
        }
    }

    // READ all
    public List<User> getAllUsers() {
        try (Session session = sessionFactory.openSession()) {
            return session.createQuery("FROM User", User.class).list();
        }
    }
}

Update and Delete Operations

Update and Delete Operations
// UPDATE - modify managed entity (auto-dirty-checking)
public void updateUserEmail(Long id, String newEmail) {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    try {
        User user = session.get(User.class, id);
        if (user != null) {
            user.setEmail(newEmail); // Hibernate detects change automatically
            // No explicit update() needed - dirty checking handles it
        }
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        throw e;
    } finally {
        session.close();
    }
}

// UPDATE - merge detached entity
public User mergeUser(User detachedUser) {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    try {
        User managed = session.merge(detachedUser); // Returns managed copy
        tx.commit();
        return managed;
    } catch (Exception e) {
        tx.rollback();
        throw e;
    } finally {
        session.close();
    }
}

// DELETE
public void deleteUser(Long id) {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    try {
        User user = session.get(User.class, id);
        if (user != null) {
            session.remove(user); // DELETE FROM users WHERE id = ?
        }
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        throw e;
    } finally {
        session.close();
    }
}

// SAVE OR UPDATE
public void saveOrUpdateUser(User user) {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    try {
        session.saveOrUpdate(user); // INSERT if id is null, UPDATE otherwise
        tx.commit();
    } catch (Exception e) {
        tx.rollback();
        throw e;
    } finally {
        session.close();
    }
}

Entity States

Hibernate entities can be in one of four states:

  • Transient: Object created with new, not associated with any Session, not in database.
  • Persistent (Managed): Associated with an open Session. Changes are automatically tracked (dirty checking) and synchronized to DB on flush/commit.
  • Detached: Was persistent but Session was closed. Changes are NOT tracked. Use merge() to re-attach.
  • Removed: Marked for deletion. Will be deleted from DB on flush/commit.

Entity State Transitions

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

// 1. TRANSIENT: not associated with session
User user = new User("alice", "alice@example.com");
// user is transient here

// 2. PERSISTENT: associated with session after persist()
session.persist(user);
// user is now persistent - changes tracked automatically

user.setEmail("newalice@example.com"); // Hibernate will UPDATE this

// 3. REMOVED: marked for deletion
session.remove(user);
// user is now removed - will be deleted on commit

tx.commit();
session.close();

// 4. DETACHED: session closed, user is detached
// user.setEmail("another@example.com"); // NOT tracked!

// Re-attach with merge
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
User managed = session2.merge(user); // user becomes managed again
tx2.commit();
session2.close();

Transaction Boundaries and Entity State

CRUD behavior depends on whether an entity is transient, managed, detached, or removed. Persist schedules a new managed entity, find loads into the persistence context, merge copies detached state into a managed instance, and remove marks a managed instance for deletion. SQL may be delayed until flush or commit.

Place a complete business change inside one transaction, not one transaction per repository call. Validate invariants before commit and remember that a failed flush makes the current transaction unusable until rollback.

Batching, Locking, and Lost Updates

Large write sets need batching, periodic flush and clear, and bounded transaction size so the persistence context does not retain every entity. Preserve deterministic ordering when database locks may be acquired by concurrent workers.

Use an @Version field for optimistic locking when concurrent edits must not silently overwrite each other. Handle the resulting conflict at the application boundary by rejecting, merging, or retrying only an operation known to be safe. Pessimistic locks are justified when conflict probability and correction cost outweigh blocking risk.

Before you move on

Hibernate CRUD save, get, update, delete Mastery Check

4 checks
  • session.persist(obj) means Insert new entity (JPA standard); a typical example is void.
  • session.save(obj) means Insert new entity (Hibernate legacy); a typical example is Serializable (ID).
  • session.get(Class, id) means Load entity by ID (returns null if not found); a typical example is Entity or null.
  • session.load(Class, id) means Load proxy by ID (throws exception if not found); a typical example is Proxy.

Hibernate Questions Learners Ask

Hibernate performs dirty checking. It snapshots managed entity state and compares changes during flush, then generates an UPDATE when needed.

A detached object may be stale, may conflict with an already managed instance, or may contain fields the client was never allowed to change. merge copies state into a managed instance and returns that managed object. In service code, loading the current entity and applying validated changes is often safer than accepting an entire detached graph.

CascadeType.REMOVE or orphanRemoval can propagate deletion through mapped relationships. That may be correct for privately owned children, but dangerous for shared entities.

Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.