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.
“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:
Problems with this approach:
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.
You just call em.persist(employee) and Hibernate generates and runs the SQL for you. No boilerplate, no connection management, no manual type conversion.
“Who calls who?”
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.
Business logic lives here. It knows what needs to happen but delegates database work to the DAO. This is also where transactions are managed.
Data Access Object — the only layer that talks to the database via EntityManager. It knows how to do CRUD but has no business rules.
Hibernate (the JPA implementation) receives the calls from EntityManager and generates the actual SQL. It's the translator between Java and the DB.
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.
“Two different things that confuse everyone”
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.
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.
| Feature | EntityManagerFactory | EntityManager |
|---|---|---|
| Created | Once at app startup | Per request / transaction |
| Thread-safe? | ✅ Yes — share it | ❌ No — one per thread |
| Cost | Expensive to create | Cheap to create |
| Analogy | The factory building | The worker inside |
| Manages | Connection pool, config | Persistence Context (cache) |
"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.
“How a Java class becomes a database table”
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.
Marks the class as JPA-managed. Without this, JPA ignores the class completely.
Specifies which DB table this entity maps to. If omitted, uses the class name.
Marks the primary key field. Every entity must have exactly one @Id.
Maps a field to a specific DB column name. If omitted, uses the field name.
Tells JPA how to handle java.util.Date — as DATE, TIME, or TIMESTAMP in the DB.
JPA requires a no-argument constructor on every entity — it uses it to recreate objects from DB results.
“The life story of an Employee object”
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).
Object created with new. JPA doesn't know about it. No DB row exists. Not in any persistence context.
→ new Employee()
JPA is tracking this object. Any changes you make will be automatically saved on commit (dirty checking!).
→ after persist() or find()
EntityManager is closed or detach() was called. JPA is no longer watching. Changes are NOT saved automatically.
→ after EM closes
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.
“Making JPA aware of your new object”
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.
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.
merge() instead)“Looking up one record by its primary key”
null if not found.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.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".
“Writing queries in Java terms, not SQL terms”
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.
| Concept | SQL | JPQL |
|---|---|---|
| Select all | SELECT * FROM employee | SELECT e FROM Employee e |
| With condition | WHERE employee_id = 1 | WHERE e.employeeId = 1 |
| Order by | ORDER BY salary DESC | ORDER BY e.salary DESC |
| Table name? | Database table name | Entity class name (case-sensitive!) |
| Column name? | Database column name | Java field name |
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!
“JPA watches your objects and saves changes automatically”
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!
🔑 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.
“Reattaching an object that JPA stopped tracking”
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.
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.
“You must find it before you can delete it”
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.
“All or nothing — the banking principle”
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).
Start a unit of work. “I'm about to do some DB operations.”
Save everything permanently. “All operations succeeded — make it permanent.”
Undo everything since begin(). “Something went wrong — undo all changes.”
Send pending SQL to DB now (but don't commit yet). JPA syncs the persistence context with the DB without ending the transaction.
“Questions you will definitely be asked”
“Last-minute revision before your interview”