⌂ Home
Unit 17 · JPA ORM & CRUD

JPA & ORM — Layman Concepts

Stop memorising jargon. Understand why JPA exists, what every piece does, and how to explain it clearly in an interview — all in plain English with real analogies.

ORM & Why It Exists EntityManager Explained 4 Entity States CRUD in Plain English JPQL vs SQL Dirty Checking Interview Q&A
Java Object @Entity EntityManager Hibernate Database Row

Why Do We Need ORM? (The Problem Statement)

“Why not just use plain SQL?”

Before JPA/ORM, every Java developer had to write raw JDBC code like this — just to save ONE employee:

// Without ORM — nightmare boilerplate Connection conn = DriverManager.getConnection("jdbc:mysql://..."); PreparedStatement ps = conn.prepareStatement("INSERT INTO employee VALUES (?, ?, ?)"); ps.setInt(1, emp.getId()); ps.setString(2, emp.getName()); ps.setDouble(3, emp.getSalary()); ps.executeUpdate(); conn.close(); // Don't forget or you leak connections!

Problems with this approach:

🏠 Real-World Analogy

Think of ORM as a Google Translate between Java and the Database. You write in Java, ORM translates it to SQL so the database understands. You read from the database, ORM translates the result back into Java objects. You never have to "speak SQL" directly.

With ORM (JPA + Hibernate)

You just call em.persist(employee) and Hibernate generates and runs the SQL for you. No boilerplate, no connection management, no manual type conversion.

How JPA Fits in Your App (Layered Architecture)

“Who calls who?”

💻 UI / Tester Layer

The starting point. Could be a main() method, JSP form, or REST controller. It talks to the Service layer with plain Java objects (DTOs). Never talks to DAO or Database directly.

⚙️ Service Layer

Business logic lives here. It knows what needs to happen but delegates database work to the DAO. This is also where transactions are managed.

🗄️ DAO Layer

Data Access Object — the only layer that talks to the database via EntityManager. It knows how to do CRUD but has no business rules.

🔌 JPA / Hibernate Layer

Hibernate (the JPA implementation) receives the calls from EntityManager and generates the actual SQL. It's the translator between Java and the DB.

🍕 Pizza Shop Analogy

UI = Customer ordering. Service = Manager deciding what to cook. DAO = Chef who actually interacts with the kitchen. JPA/Hibernate = The recipe book that translates the order into cooking steps. Database = The actual ingredients pantry.

EntityManagerFactory vs EntityManager

“Two different things that confuse everyone”

🏭 EntityManagerFactory (EMF)

Created once when the app starts. It's expensive to create (reads persistence.xml, connects to DB, sets up Hibernate). Think of it as the factory/plant that produces workers. You build the factory once, then ask it to produce workers whenever needed.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("employeePU");

👷 EntityManager (EM)

Created per request (or per transaction). Cheap to create and manages one persistence context (its own first-level cache). Think of it as a worker/employee that does actual database work for one session, then is dismissed.

EntityManager em = emf.createEntityManager();
FeatureEntityManagerFactoryEntityManager
CreatedOnce at app startupPer request / transaction
Thread-safe?✅ Yes — share it❌ No — one per thread
CostExpensive to createCheap to create
AnalogyThe factory buildingThe worker inside
ManagesConnection pool, configPersistence Context (cache)
🚨 Interview Trap

"Is EntityManager thread-safe?" — NO! Each thread (request) must have its own EntityManager. EMF is thread-safe and shared. EM is NOT thread-safe.

What is persistence.xml?

It's a config file in META-INF/persistence.xml that tells JPA: which database to connect to, which driver to use, which entity classes to manage, and which Hibernate settings to apply. Think of it as the recipe card that EMF reads to know how to set up the system.

What is a JPA Entity?

“How a Java class becomes a database table”

📄 Analogy

A Java class = Database Table structure. An object of that class = one Row in the table. Fields = Columns. JPA annotations are the “translation instructions” telling Hibernate how to map each.

@Entity // "This class is a DB table" @Table(name = "employee") // table name in DB public class Employee { @Id // Primary key column @Column(name = "employee_id") private int employeeId; @Column(name = "employee_name") private String employeeName; private double salary; // column name = "salary" by default @Temporal(TemporalType.DATE) // Date type in DB private Date joiningDate; }

@Entity

Marks the class as JPA-managed. Without this, JPA ignores the class completely.

@Table

Specifies which DB table this entity maps to. If omitted, uses the class name.

@Id

Marks the primary key field. Every entity must have exactly one @Id.

@Column

Maps a field to a specific DB column name. If omitted, uses the field name.

@Temporal

Tells JPA how to handle java.util.Date — as DATE, TIME, or TIMESTAMP in the DB.

No-arg Constructor

JPA requires a no-argument constructor on every entity — it uses it to recreate objects from DB results.

The 4 States of an Entity Object

“The life story of an Employee object”

🧑‍💼 Employee Career Analogy

Think of an entity object like an employee's career: New (applied, no job yet) → Managed (hired, actively employed) → Detached (on leave/resigned) → Removed (fired, will be gone).

1. NEW (Transient)

Object created with new. JPA doesn't know about it. No DB row exists. Not in any persistence context.

new Employee()

2. MANAGED

JPA is tracking this object. Any changes you make will be automatically saved on commit (dirty checking!).

→ after persist() or find()

3. DETACHED

EntityManager is closed or detach() was called. JPA is no longer watching. Changes are NOT saved automatically.

→ after EM closes

4. REMOVED

Marked for deletion. JPA will run DELETE SQL on transaction commit. Object still exists in memory until then.

→ after remove()

🔑 Key insight: Only objects in MANAGED state are tracked by JPA. When a transaction commits, JPA flushes all changes from managed entities to the database automatically.

persist() — How to Save a New Record

“Making JPA aware of your new object”

📋 Analogy

persist() is like handing your CV to HR. You hand it over (persist), HR registers you (managed state), and only on the day you join (commit/flush) does the actual INSERT happen in the database.

Employee emp = new Employee(); // State: NEW emp.setName("Rahul"); emp.setSalary(50000); em.getTransaction().begin(); // Start a transaction em.persist(emp); // State: MANAGED — JPA is now watching em.getTransaction().commit(); // SQL INSERT runs NOW
🚨 Common Mistake

persist() does NOT immediately run an INSERT. It schedules it. The actual INSERT SQL runs when the transaction is committed. Many beginners think calling persist() is enough — but without commit(), nothing reaches the database.

find() — How to Fetch a Record by ID

“Looking up one record by its primary key”

Employee emp = em.find(Employee.class, 1); // Generates: SELECT * FROM employee WHERE employee_id = 1

find() behaviour

  • First checks the first-level cache (persistence context). If the object was already loaded, it returns the cached copy — no SQL query!
  • If not in cache, hits the database.
  • Returns null if not found.
  • Returned object is in MANAGED state.

⚠️ find() vs getReference()

  • find() — Hits DB immediately, returns full object or null.
  • getReference() — Returns a proxy (lazy placeholder). DB is hit only when you access a field. Throws exception if not found.
🚨 Interview Trap

The second argument to find() is the primary key value (the value of the @Id field), NOT just any column value. em.find(Employee.class, "Rahul") would look for an employee with ID "Rahul", not name "Rahul".

JPQL — Query All Records (Not Just One)

“Writing queries in Java terms, not SQL terms”

🌐 Analogy

Regular SQL talks about tables and columns (SELECT * FROM employee). JPQL talks about Java classes and fields (SELECT e FROM Employee e). JPQL is object-oriented SQL — Hibernate converts it to real SQL at runtime.

ConceptSQLJPQL
Select allSELECT * FROM employeeSELECT e FROM Employee e
With conditionWHERE employee_id = 1WHERE e.employeeId = 1
Order byORDER BY salary DESCORDER BY e.salary DESC
Table name?Database table nameEntity class name (case-sensitive!)
Column name?Database column nameJava field name
List<Employee> list = em.createQuery( "SELECT e FROM Employee e", Employee.class) .getResultList(); // With parameter List<Employee> list = em.createQuery( "SELECT e FROM Employee e WHERE e.role = :r", Employee.class) .setParameter("r", "Manager") .getResultList();
🚨 JPQL Gotcha

In JPQL, Employee refers to the Java class name, not the database table name. So if your class is Employee but your table is tbl_employee, JPQL still uses Employee. It's case-sensitive!

Dirty Checking — The “Magic” Auto-Update

“JPA watches your objects and saves changes automatically”

📷 Analogy

When you find() an entity, JPA takes a snapshot photo of the object. When the transaction commits, JPA takes another photo and compares the two. If anything changed (it's “dirty”), JPA automatically generates an UPDATE SQL. You never have to call any update method!

em.getTransaction().begin(); Employee emp = em.find(Employee.class, 1); // MANAGED — JPA takes a snapshot emp.setSalary(75000); // You just changed the object // No em.update() needed! em.getTransaction().commit(); // JPA detects change, runs UPDATE automatically

🔑 Dirty checking only works on MANAGED entities. If the entity is DETACHED (EM is closed, or you fetched it in a different session), changes are NOT tracked. You must use merge() instead.

merge() — Updating a Detached Entity

“Reattaching an object that JPA stopped tracking”

🔄 Analogy

merge() is like bringing an old employee back from leave. The company (JPA) doesn't know what they did while away. You hand back the updated copy and the company merges the changes into the official record. The returned object from merge() is the new managed version — not the original you passed in.

// emp is DETACHED (came from a web form or a previous session) emp.setSalary(80000); em.getTransaction().begin(); Employee managedEmp = em.merge(emp); // Returns MANAGED copy em.getTransaction().commit(); // UPDATE runs for managedEmp
🚨 Interview Trap

merge() returns a new managed object. The original object you passed in is still DETACHED. Use the return value: Employee managed = em.merge(detached); — never continue working with the original detached variable after merging.

remove() — Deleting a Record

“You must find it before you can delete it”

em.getTransaction().begin(); Employee emp = em.find(Employee.class, 1); // Must be MANAGED em.remove(emp); // State: REMOVED em.getTransaction().commit(); // DELETE FROM employee WHERE employee_id = 1
🚨 Interview Trap

remove() only works on MANAGED entities. You cannot pass a detached object directly. If your entity is detached, first merge() it to get a managed copy, then call remove() on the managed copy.

Why Transactions Matter (Plain English)

“All or nothing — the banking principle”

🏦 Bank Transfer Analogy

Transferring money from Account A to Account B involves two operations: Debit A and Credit B. If the app crashes after debiting A but before crediting B, money disappears. A transaction wraps both operations and guarantees: either both succeed (commit) or both are undone (rollback).

begin()

Start a unit of work. “I'm about to do some DB operations.”

commit()

Save everything permanently. “All operations succeeded — make it permanent.”

rollback()

Undo everything since begin(). “Something went wrong — undo all changes.”

flush()

Send pending SQL to DB now (but don't commit yet). JPA syncs the persistence context with the DB without ending the transaction.

try { em.getTransaction().begin(); em.persist(emp1); em.persist(emp2); em.getTransaction().commit(); // Both saved or nothing } catch (Exception e) { em.getTransaction().rollback(); // Undo everything on error }

Top Interview Questions with Answers

“Questions you will definitely be asked”

What is ORM and why do we use it?
ORM (Object-Relational Mapping) is a technique that converts data between Java objects and database tables automatically. We use it to avoid writing repetitive JDBC boilerplate, eliminate type mismatch problems, and write queries in Java terms instead of raw SQL strings.
What is the difference between JPA and Hibernate?
JPA is a specification (a set of rules/interfaces). Hibernate is an implementation of those rules. JPA defines what methods should exist (like persist, merge, find). Hibernate actually implements those methods. Using JPA API keeps your code portable — if you want, you can switch from Hibernate to EclipseLink without changing your code.
What is the difference between EntityManagerFactory and EntityManager?
EntityManagerFactory (EMF) is created once at startup, is thread-safe, and manages the connection pool. EntityManager (EM) is created per-request/transaction, is NOT thread-safe, and manages one persistence context (a unit of work). EMF is expensive to create; EM is cheap. Always close EM after use to avoid memory leaks.
What are the 4 states of a JPA entity?
1) New/Transient — created with new, JPA unaware. 2) Managed — JPA is tracking it, changes auto-saved on commit. 3) Detached — JPA stopped tracking (EM closed), changes NOT auto-saved. 4) Removed — marked for deletion, DELETE SQL runs on commit.
What is dirty checking in JPA?
Dirty checking is JPA's automatic change detection. When you load a managed entity with find(), JPA takes a snapshot. On transaction commit, JPA compares the current state with the snapshot. If any fields changed (entity is "dirty"), JPA automatically generates an UPDATE SQL. No manual em.update() call is needed.
When do you use merge() vs persist()?
Use persist() to save a brand new entity (state: New → Managed). Use merge() to reattach a detached entity and save its changes. merge() returns a new managed copy — always use the return value, not the original detached object.
What is JPQL and how is it different from SQL?
JPQL (Java Persistence Query Language) uses Java class names and field names instead of database table and column names. SQL says "SELECT * FROM employee", JPQL says "SELECT e FROM Employee e". Hibernate converts JPQL to the appropriate SQL dialect for your database at runtime.
What is a Persistence Context?
A Persistence Context is the in-memory first-level cache managed by EntityManager. It keeps track of all managed entities during a transaction. If you call find() twice for the same ID in the same transaction, only one SQL query is made — the second call returns the cached object. It's cleared when the EntityManager is closed.

⚡ Memory Cheat Sheet

“Last-minute revision before your interview”

persist()
New → Managed
INSERT on commit
find()
SELECT by @Id
Returns null if missing
JPQL
Uses class/field names
Not table/column names
Dirty Check
Auto UPDATE
Managed entities only
merge()
Detached → Managed copy
Use the RETURN VALUE
remove()
Need MANAGED entity first
DELETE on commit
EMF
Created ONCE
Thread-safe ✅
EM
Per request/transaction
NOT thread-safe ❌
JPA vs Hibernate
JPA = Spec (rules)
Hibernate = Implementation
↑ Back to top