Hibernate Fundamentals

Hibernate Architecture

Understand the layers and core objects Hibernate uses to connect Java applications with relational databases.

Hibernate Architecture Overview

Hibernate architecture is built from objects that coordinate object-relational mapping, database connections, transactions, queries, and persistence state. A Java application works with domain objects and Hibernate APIs, while Hibernate translates that work into JDBC calls and SQL.

Java applicationHibernate frameworkJDBC / JTA / JNDIDatabase

Layers of Hibernate Architecture

Hibernate is commonly explained using four cooperating layers:

Java Application Layer

The top layer contains Java classes, business logic, services, and user interactions. Application code uses Hibernate or Jakarta Persistence APIs to perform database operations.

Hibernate Framework Layer

This layer contains ORM components such as Session, SessionFactory, Transaction, queries, mappings, and configuration. It manages the relationship between objects and relational data.

Back-End API Layer

JDBC provides database connectivity. JTA can coordinate transactions in managed environments, and JNDI can locate configured resources. These APIs bridge Hibernate and infrastructure.

Database Layer

The bottom layer is the relational database, such as MySQL, PostgreSQL, Oracle, or SQL Server. Hibernate reads, inserts, updates, and deletes data through the back-end APIs.

Elements of Hibernate Architecture

ElementResponsibilityTypical lifetime
SessionFactoryCreates sessions and owns shared configuration and optional second-level cache.Application-wide, expensive to create
SessionRepresents a unit of work and persistence context for loading and changing entities.Short-lived, not thread-safe
TransactionGroups database work into an atomic commit or rollback boundary.Per unit of work
ConnectionProviderSupplies and releases JDBC connections, often through a pool or DataSource.Managed by Hibernate
TransactionCoordinatorIntegrates Hibernate transaction handling with JDBC or JTA transactions.Managed internally
Persistent objectAn entity whose state is tracked by the current persistence context.While attached to a session
Version note: older Hibernate material often calls this component TransactionFactory. Modern Hibernate versions use transaction coordination services and integrations rather than exposing that older factory as the central application concept.

SessionFactory

SessionFactory is a thread-safe, application-wide factory for Hibernate sessions. Building it reads mappings and configuration, so it should normally be created once and reused. It can also coordinate shared services and an optional second-level cache.

SessionFactory sessionFactory = ...;

try (Session session = sessionFactory.openSession()) {
    // Perform one unit of work.
}

Session

A Session represents a short-lived unit of work and contains the first-level cache, also called the persistence context. It loads entities, tracks changes, creates queries, and provides access to transactions. A session is not thread-safe; do not share one session across concurrent requests.

try (Session session = sessionFactory.openSession()) {
    Employee employee = session.find(Employee.class, 101L);
    // employee is managed while it belongs to this session.
}

Transaction

A transaction defines an atomic unit of database work. Successful work is committed; failures can be rolled back. In modern applications, transaction boundaries are often managed by Spring or JTA, but the same atomicity principle applies.

Transaction transaction = session.beginTransaction();
try {
    session.persist(new Employee("Anand"));
    transaction.commit();
} catch (RuntimeException exception) {
    transaction.rollback();
    throw exception;
}

ConnectionProvider

ConnectionProvider abstracts how Hibernate obtains and releases JDBC connections. It can work with a configured DataSource or connection pool instead of requiring application code to call DriverManager directly. Keeping connection management behind this service improves portability and operational control.

TransactionFactory and Transaction Coordination

Older Hibernate tutorials describe a TransactionFactory that creates transaction objects. Current Hibernate architecture uses transaction coordination services to integrate local JDBC transactions or JTA-managed transactions. Application developers should normally use the transaction API supplied by their Hibernate or Spring integration rather than constructing internal services.

Hibernate Entity States

An entity can move through four primary states: transient, persistent, detached, and removed. These states determine whether Hibernate manages the object, performs dirty checking, and synchronizes changes with the database.

Transient -- persist() --> Persistent -- detach(), clear(), close() --> Detached -- merge() --> Persistent -- remove() --> Removed

1. Transient State

A transient entity is a normal Java object that is not associated with a Hibernate session or persistence context. Hibernate does not manage it, perform dirty checking for it, or automatically store its changes.

Employee employee = new Employee();
employee.setName("Anand");
employee.setDepartment("Engineering");

session.persist(employee); // Transient -> Persistent

2. Persistent State

A persistent entity is associated with an active session and persistence context. Hibernate stores it in the first-level cache, tracks relationships, and detects changes through dirty checking.

Employee employee = session.find(Employee.class, 1L);
employee.setDepartment("Architecture");

// Hibernate can flush:
// UPDATE employee SET department = ? WHERE id = ?;

An entity returned by session.find() or a Hibernate query is normally persistent while it remains associated with the session.

3. Detached State

A detached entity was previously persistent but is no longer connected to an active persistence context. This happens when a session is closed or when detach(), clear(), or eviction is used.

Employee employee = entityManager.find(Employee.class, 1L);
entityManager.detach(employee);
employee.setName("Updated Name"); // Not automatically saved

Employee managed = entityManager.merge(employee);

merge() copies the detached object’s state into a managed object and returns that managed object. The original and returned references are generally different, so continue working with managed.

4. Removed State

A removed entity is a managed entity scheduled for deletion. Hibernate usually sends the delete statement during flush or transaction commit.

Employee employee = entityManager.find(Employee.class, 1L);
entityManager.remove(employee);
// DELETE FROM employee WHERE id = ?;

Entity-State Comparison

StateManaged?Database rowDirty checkingTypical operation
TransientNoUsually noNonew
PersistentYesExisting or pending insertYespersist() or find()
DetachedNoUsually yesNodetach() or session close
RemovedYes until completionScheduled for deletionDelete trackedremove()

Dirty Checking and Entity States

Dirty checking works only for persistent entities. Hibernate compares a managed entity with its original state and generates the required update during flush.

@Transactional
public void updateEmployee(Long employeeId) {
    Employee employee = entityManager.find(Employee.class, employeeId);
    employee.setName("Updated Name");
}

After detach(), changing the same object does not automatically update the database because Hibernate no longer manages it.

persist(), merge(), remove(), detach(), clear(), and refresh()

persist()

Moves a transient object to persistent state.

merge()

Copies transient or detached state into a managed instance.

remove()

Marks a persistent entity for deletion.

detach()

Removes one entity from the persistence context.

clear()

Detaches every entity in the persistence context.

refresh()

Reloads the current entity state from the database.

For large batches, periodically call flush() and clear() to synchronize changes and limit first-level-cache growth.

A Typical Hibernate Request Lifecycle

  1. Application code receives a request and starts a unit of work.
  2. A session is obtained from the shared SessionFactory.
  3. A transaction begins.
  4. Hibernate loads or persists entities through the session.
  5. Dirty checking detects changes and Hibernate flushes SQL through JDBC.
  6. The transaction commits or rolls back.
  7. The session closes and its first-level cache is discarded.
Practical rule: keep sessions and transactions short, never share a session between threads, and inspect generated SQL when diagnosing performance or correctness problems.