Careeroza
Session Lifecycle
SessionFactory and Session
SessionFactory (JPA: EntityManagerFactory) is built once at startup. It is heavy: it parses all mappings, prepares SQL for every entity and holds the L2 cache. It is thread-safe and shared.
Session (JPA: EntityManager) is light and not thread-safe. It holds the persistence context, an action queue of pending SQL, and a JDBC connection while it needs one. In Spring, the injected EntityManager is a proxy that finds the Session bound to the current transaction.
One Request, Step by Step
@Transactional method called │ Spring: JpaTransactionManager opens a Session, begins a transaction, │ binds Session to the current thread ▼ find / query → persistence context fills up (entities + snapshots) setters → nothing happens yet (just Java fields) persist / remove → actions added to the ACTION QUEUE ▼ method returns │ Spring: commit → Session.flush() │ 1. dirty checking: compare entities with snapshots → UpdateActions │ 2. action queue executes in order: │ inserts → updates → collection changes → deletes │ → JDBC commit → Session closed, entities become DETACHED ▼ response serialised (lazy fields now throw unless OSIV is on)
Action Queue Order
Hibernate does not run SQL in the order you called methods. At flush it runs: orphan removals → inserts → updates → collection element removals → collection inserts → deletes. This order avoids most foreign-key problems, but it surprises people:
@Transactional
public void replaceSku(Long oldId) {
Product old = em.find(Product.class, oldId);
em.remove(old); // queued as a DELETE
Product fresh = new Product();
fresh.setSku(old.getSku()); // same unique SKU
em.persist(fresh); // queued as an INSERT
} // flush: INSERT runs before DELETE -> unique constraint violation on sku!
// Fix: force the delete out first
em.remove(old);
em.flush(); // DELETE executed now
em.persist(fresh);