JPA Fundamentals
About
JPA (Java Persistence API) is more than just annotations and queries — it provides a complete framework for managing the lifecycle of Java objects and synchronizing them with a relational database.
Entities and the Persistence Context
An entity is a lightweight, persistent domain object that represents a table in the database.
When we persist or retrieve entities in JPA, they live inside something called the persistence context, which acts like a mini in-memory database for tracking and managing those entities.
An Entity in JPA is a Java class mapped to a database table.
What is a Persistence Context ?
It is a kind of cache that keeps track of all the entities we’ve loaded or saved within a single transaction/session.
If we load the same entity twice, JPA will return the same object instance.
Changes to entities are automatically detected and synchronized to the database (this is called dirty checking).
EntityManager
The EntityManager
is the main interface used to interact with JPA.
It provides methods to
Create or remove entities
Find or load entities by ID
Execute queries
Manage transactions (in some cases)
Key Methods
persist(entity)
→ Save a new entityfind(Entity.class, id)
→ Fetch an entity by its primary keymerge(entity)
→ Update an existing entityremove(entity)
→ Delete an entitycreateQuery(...)
→ Execute JPQL queries
Entity Lifecycle States
An entity in JPA can exist in different states during its lifecycle. These states control the interaction between the entity and the persistence context, and they help manage the process of saving, updating, deleting, and retrieving entities from the database.
The JPA lifecycle states are as follows:
New (Transient)
Managed (Persistent)
Detached
Removed
1. New (Transient) State
An entity in the New state is created in memory but not yet associated with a persistence context (i.e., it is not yet persisted in the database).
Key characteristics
The entity is not managed by JPA.
It has no database identity because it doesn't have an associated record in the database yet.
If we try to persist it, JPA will assign it a database identity.
Example
Transition to Managed State
To transition this entity to the Managed state, we need to call persist()
using the EntityManager
.
2. Managed (Persistent) State
When an entity is in the Managed state, it is associated with a persistence context, and any changes made to the entity will be tracked by JPA. JPA automatically synchronizes these changes to the database (either when the transaction is committed or when explicitly flushed).
Key characteristics
JPA is aware of the entity, and any modifications to it are automatically persisted to the database at commit time.
The entity is cached within the persistence context.
If you modify the entity, JPA detects the changes (this is known as dirty checking) and will update the database when the transaction is committed.
Example
Transition to Detached or Removed:
Detached: The entity becomes detached from the persistence context (e.g., after the transaction is committed and the persistence context is closed).
Removed: The entity is deleted from the database by calling
remove()
.
3. Detached State
An entity becomes Detached when it is no longer managed by the persistence context. This typically happens after the transaction ends or the persistence context is closed. The entity can still be used, but JPA no longer tracks it for changes.
Key characteristics
The entity is no longer associated with the persistence context.
Any changes made to the entity will not be automatically saved to the database.
It can still be reattached to a persistence context if needed (e.g., by calling
merge()
).
Example
Reattaching Detached Entities: If you want to reattach a detached entity to the persistence context (so changes can be tracked again), you can use the merge()
method:
Transition to Managed:
The entity can be reattached to the persistence context using merge()
, bringing it back to the Managed state.
4. Removed State
An entity is in the Removed state when it has been marked for deletion and is scheduled to be deleted from the database. Once an entity is removed, it is no longer part of the persistence context and will be deleted when the transaction is committed.
Key characteristics
Once removed, the entity is not available for further operations unless it is reinserted.
The entity is marked for deletion, and its corresponding database row is deleted when the transaction is committed.
It cannot be updated or persisted again until it is recreated as a new entity.
Example
Transition from Removed:
Once an entity is removed, it cannot transition back to the Managed state.
If you want to persist it again, you would need to create a new instance and persist it.
Persistence Unit
A Persistence Unit is a logical grouping of:
Entity classes
Configuration metadata
Database connection details
And other properties required by the JPA provider (like Hibernate)
It's the core definition of how JPA should behave for a given application or module.
A persistence unit is traditionally declared in a file called persistence.xml
, but in Spring (especially Spring Boot), this is now mostly replaced by Java-based or Spring Boot property-based configuration.
Why Persistence Unit Exists ?
The Java EE specification required a standard way to define:
Which entities are to be managed
Which datasource to use
Which JPA implementation to use
How transactions are handled
Thus, the persistence.xml
was introduced.
It allows:
Reusability (we can define multiple units)
Vendor-agnostic configuration
Container-managed deployment
Traditional persistence.xml
Structure
persistence.xml
StructureLocated in:
Example
How it works internally?
When the application starts:
The JPA provider scans
META-INF/persistence.xml
It identifies the persistence unit(s)
It builds a
PersistenceUnitInfo
objectThen creates the
EntityManagerFactory
based on it
Do we still need persistence.xml
in Spring Boot?
persistence.xml
in Spring Boot?No. In Spring Boot, the need for persistence.xml
is removed because:
Spring Boot auto-configures the datasource, JPA provider, and entity scanning.
Entities are discovered from your classpath.
Configuration is handled via
application.properties
orapplication.yml
.
Instead of persistence.xml
, we write
Behind the scenes, Spring Boot creates a default persistence unit and configures EntityManagerFactory
using this info.
Transaction Management
JPA requires a transaction to:
Persist new entities
Update or delete existing ones
Run any modifying query
In a Java EE or Spring environment, this is usually handled using @Transactional
.
Without a transaction:
Reads may work
Writes will often fail or behave unpredictably
What is a Dialect in JPA
In JPA (specifically Hibernate or other providers), a Dialect is a class that tells Hibernate how to generate SQL for a specific database.
It knows:
How to write
SELECT
,INSERT
,UPDATE
,DELETE
.What data types the database supports (
VARCHAR
,TEXT
,BLOB
, etc.).What special database features exist (like auto-increment, sequences, functions).
Every database (MySQL, Oracle, PostgreSQL, SQL Server) has its own SQL syntax rules and special features. The Dialect acts like a "translator" between Hibernate and your database.
MySQL
org.hibernate.dialect.MySQLDialect
PostgreSQL
org.hibernate.dialect.PostgreSQLDialect
Oracle
org.hibernate.dialect.OracleDialect
SQL Server
org.hibernate.dialect.SQLServerDialect
Spring Boot Example in application.properties
:
Tells Hibernate: "Hey, generate SQL that works correctly with MySQL."
Example: MySQL uses
LIMIT
keyword for pagination, while Oracle usesROWNUM
. The dialect handles these differences automatically.
How Hibernate uses Dialect internally
When we create an entity and Hibernate tries to create or update a table, it looks at the Dialect to know:
How to define columns (
VARCHAR(255)
,TEXT
, etc.).How to generate keys (like
AUTO_INCREMENT
for MySQL vsSEQUENCE
for Oracle).How to build queries that match your database syntax.
If the wrong dialect is chosen, Hibernate might generate wrong SQL, and your app will fail at runtime.
Last updated
Was this helpful?