ReviseAlgo Logo

Spring Data JPA & Hibernate

JPA and Hibernate Fundamentals — ORM Explained

Object-Relational Mapping, entity states, session management, and first/second level caches.

Last Updated: June 14, 2026 15 min read

Introduction

In object-oriented Java applications, data is represented as a graph of objects. In relational databases, data is represented as tables, columns, and foreign keys. This structural mismatch is known as the Object-Relational Impedance Mismatch.

Object-Relational Mapping (ORM) acts as a bridge. The Jakarta Persistence API (JPA) is the standard Java specification that defines how to map Java objects to relational tables. Hibernate is the most widely used implementation of the JPA specification.

Why It Matters

Without an ORM, developers must write boilerplate JDBC code to map SQL ResultSet rows to Java objects manually. Hibernate automates this mapping, implements automatic dirty checking (detecting object modifications and issuing SQL UPDATE statements), and provides internal caches (First-Level and Second-Level) to minimize database roundtrips.

Real-World Analogy

Think of JPA/Hibernate like a simultaneous translator at an international summit. The Java Application speaks "Objects" (classes, interfaces, pointers), while the Database speaks "SQL" (tables, primary keys, rows). Hibernate sits in the middle: when you update a Java object, Hibernate translates that change and updates the database row in SQL automatically, ensuring both parties understand each other without writing manual dictionary lookups.

Detailed Mechanics

1. The Persistence Context & Session

The Persistence Context is a temporary storage area (an in-memory cache) where JPA manages entities. The EntityManager (or Hibernate's Session) controls access to this context. Within a transaction, any entity loaded from the database is placed in the persistence context.

2. Entity Lifecycle States

An entity can exist in one of four states:

  • Transient: The object has been instantiated in memory (using new) but is not associated with an EntityManager or a database record.
  • Managed (Persistent): The object is associated with an active persistence context and has a corresponding row in the database. Any changes made to managed entities are automatically tracked and synchronized to the database when the transaction commits (dirty checking).
  • Detached: The object exists in the database, but its association with the active persistence context has been closed or cleared (e.g., after the transaction commits or if entityManager.detach() is called). Changes to detached objects are not tracked.
  • Removed: The object is marked for deletion in the database and will be deleted during the next flush.
State In Database? Managed by Hibernate? Dirty Checking?
Transient No No No
Managed Yes Yes Yes
Detached Yes No No
Removed Yes (until flush) Yes No

3. Hibernate Cache Levels

  • First-Level Cache (L1 Cache): This is the Persistence Context itself. It is mandatory, associated with the current thread's transaction session, and prevents fetching the same entity multiple times in a single transaction.
  • Second-Level Cache (L2 Cache): An optional, pluggable cache that is shared across all sessions/transactions. It caches entities across query threads, reducing DB queries globally (e.g., using Redis or Ehcache).

Practical Example

Quick Quiz

Q1: Which entity state is an object in after its session has been closed?

A) Transient

B) Detached

C) Persistent

D) Removed

Answer: B — When the managing persistence context/session is closed, all entities become detached.

Q2: How does dirty checking work in Hibernate?

A) Hibernate polls the database to see if values have changed.

B) You must call update() every time you modify an entity field.

C) At transaction commit/flush, Hibernate compares the entity's current state with its initial loaded state copy (snapshot) in the L1 Cache.

D) It updates the DB using reflection callbacks on setter methods.

Answer: C — Hibernate keeps a snapshot copy of loaded entities and detects delta changes during the flush phase.

Scenario-Based Challenge

Production Scenario:

A batch processing service loads 50,000 customers from the database within a single transaction, updates their status, and saves them. After running for a few minutes, the application throws an OutOfMemoryError. Why did this happen and how do you fix it?

View Solution

This happens because all 50,000 entities remain managed in the First-Level Cache (L1 Cache/Persistence Context) for the entire duration of the transaction. To fix this, you should batch the updates and periodically flush and clear the Persistence Context:

Interview Questions

1. Conceptual: What is the difference between JPA and Hibernate?

JPA is a specification (a set of guidelines and interfaces under the Jakarta namespace), whereas Hibernate is a concrete implementation of that specification. You write code using JPA annotations (e.g., jakarta.persistence.*) so you can easily swap out Hibernate for another provider (like EclipseLink) if needed.

2. Coding: What is the behavior of the following block?

The price will be updated in the database automatically because find() loads the entity into the Persistence Context, placing it in the Managed state. During the transaction commit, dirty checking detects that the price was modified and flushes a SQL UPDATE statement to the database automatically.

Production Considerations

Avoid working with detached entities directly when possible. Using entityManager.merge() can perform hidden SELECT queries to check database state before executing updates. If updating an entity, it is always safer and more efficient to load it within a transactional method, modify its fields, and let dirty checking update it automatically.