JPA Transactions
In Spring, you add the @Transactional annotation on a method. The framework then starts a session when the method begins. It commits all transactions in the thread when the method returns.
A flow may have many @Transactional methods. They share the same transaction, the outermost one, unless you say otherwise.
For methods without this annotation:
- Calls through spring-data CrudRepository already have this annotation. The transaction is handled there.
- With direct calls, each query is its own transaction. It runs and commits on its own.
Thread Safe Componentsโ
The following components are thread-safe in a JPA transaction
- Entity Manager - All work with the database and the persistent context goes through this.
- Persistent Context - Think of it as a map of DB entities the thread knows. It's also called the L1 cache.
Shared Componentsโ
The following components are shared across threads
- L2 Cache - It can share DB entities across many threads. For example, Hibernate clears a cache entry when an entity is updated.
- Connection Pool - The database connections are created once and shared between threads.
The connection pool keeps the DB connection alive at all times.
It just connects to the database URL, sends the credentials, and stays ready to start a session.
It uses TCP keep-alive to keep the connection active while the pool is active.

Proxy Classesโ
The Spring framework doesn't weave the start and end code into the real classes. Instead, if a class has a transactional annotation, Spring creates a proxy class and its bean. The calling app then uses these.
This proxy bean first starts the transaction. Then it calls the real bean.
If you create and call a class directly, the proxy is skipped. The transaction isn't managed.
Lockingโ
JPA and Hibernate build the database locking features.
Read more about database locking in the locking page.