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
ResultSetiteration. - 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 │
└───────────────┘
- Transient (New): Just instantiated with
new User(). Has no database identity (primary key is null) and is unknown to the persistence context. - Persistent (Managed): Associated with an active
EntityManagerand has a database ID. Any property change triggers dirty checking and is synchronized with the database upon commit without callingsave()! - Detached: Had a database identity and was managed, but the
EntityManageror transaction closed. Changes are no longer tracked. - Removed: Scheduled for deletion (
DELETEexecuted 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!
}