Skip to main content

5.1 JPA & Hibernate Fundamentals

← Back to Chapter 5: Spring Data JPA, Hibernate & Database

Relational databases store tabular relations, whereas Java represents objects in memory. Object-Relational Mapping (ORM) bridges this paradigm impedance mismatch.

Spring Data JPA → Repository abstraction

JPA → Specification

Hibernate → JPA implementation

1. The Stack: JDBC vs JPA vs Hibernate vs Spring Data​

┌───────────────────────────────────────────────────────────┐
│ Spring Data JPA (Repository interfaces, derived queries) │
├───────────────────────────────────────────────────────────┤
│ JPA Specification (jakarta.persistence.* interfaces) │
├───────────────────────────────────────────────────────────┤
│ Hibernate ORM (The actual concrete JPA implementation) │
├───────────────────────────────────────────────────────────┤
│ JDBC Driver (Translates SQL calls into database network) │
├───────────────────────────────────────────────────────────┤
│ Relational Database (PostgreSQL, MySQL, Oracle) │
└───────────────────────────────────────────────────────────┘
  • JDBC: Low-level API requiring manual connection management, SQL string writing, and ResultSet iteration.
  • JPA (Jakarta Persistence): The official Java standard specification defining interfaces (EntityManager, @Entity). It contains zero executable code!
  • Hibernate: The industry-standard ORM engine implementing the JPA specification.
  • Spring Data JPA: Abstraction layer built on top of JPA that eliminates boilerplate DAO implementation code via repository interfaces.

2. The 4 JPA Entity Lifecycle States​

An entity object exists in one of four distinct states within the persistence context (EntityManager):

[ new Entity() ]
│
│ persist()
▼
┌───────────────┐ detach() / close() ┌───────────────┐
│ PERSISTENT ├─────────────────────>│ DETACHED │
│(Managed by EM)│<─────────────────────┤ │
└───────┬───────┘ merge() └───────────────┘
│
│ remove()
▼
┌───────────────┐
│ REMOVED │
└───────────────┘
  1. Transient (New): Just instantiated with new User(). Has no database identity (primary key is null) and is unknown to the persistence context.
  2. Persistent (Managed): Associated with an active EntityManager and has a database ID. Any property change triggers dirty checking and is synchronized with the database upon commit without calling save()!
  3. Detached: Had a database identity and was managed, but the EntityManager or transaction closed. Changes are no longer tracked.
  4. Removed: Scheduled for deletion (DELETE executed upon transaction commit).

3. The First-Level Cache & Dirty Checking​

Within a @Transactional boundary, the EntityManager maintains a First-Level Cache:

@Transactional
public void updateEmail(Long userId, String newEmail) {
// Query 1: Hits database, populates 1st-level cache
User user1 = userRepository.findById(userId).orElseThrow();

// Query 2: Cache hit! No SQL executed against DB!
User user2 = userRepository.findById(userId).orElseThrow();

// Dirty checking in action:
user1.setEmail(newEmail);
// No userRepository.save(user1) is required! Hibernate automatically flushes changes on commit!
}