Java Persistence API (JPA)
JPA는 Java Persistence API의 약자로, 자바 진영에서 관계형 데이터베이스와 객체 지향 프로그래밍 간의 데이터를 매핑하고 관리하기 위한 표준 인터페이스입니다.
이는 개발자가 데이터베이스에 대한 저수준의 코드 작성을 줄이고, 객체 지향적인 방식으로 데이터를 다룰 수 있게 돕습니다.
JPA는 객체 지향 프로그래밍의 개념과 관계형 데이터베이스의 테이블 간의 매핑을 처리하기 위한 ORM(Object-Relational Mapping) 기술을 기반으로 합니다.
JPA의 역할
JPA는 ORM 개념을 추상화하여 표준 인터페이스로 제공하며, 다양한 ORM 프레임워크를 JPA 구현체로 사용할 수 있도록 합니다.
이를 통해 개발자는 일관성 있고 편리하게 객체와 데이터베이스 간의 매핑을 처리할 수 있습니다.
JPA는 엔티티(Entity) 클래스를 정의하고, 이를 데이터베이스의 테이블과 매핑하는 어노테이션 기반의 설정을 제공합니다.
JPA 동작 원리
- F : Filter
- DS : DispatcherServlet
- C : Controller
- S : Service
- R : Repository
- PC(영속성 컨텍스트) : Persist Context
- DB 안의 것들은 테이블입니다
1단계: Proxy 객체
JPA는 데이터베이스에서 데이터를 조회할 때, 실제 엔티티 객체 대신에 프록시 객체를 사용할 수 있습니다.
프록시 객체는 실제 엔티티 객체와 같은 인터페이스를 가지지만, 실제 엔티티 객체의 데이터를 로드하는 것을 지연시킬 수 있습니다.
이를 통해 필요한 시점에만 데이터를 로드하여 성능을 향상시킬 수 있습니다.
User user = entityManager.getReference(User.class, userId);
2단계: Persist Context와 비영속 객체
비영속 객체는 아직 JPA의 영속성 컨텍스트에 포함되지 않은 상태의 객체를 말합니다.
이 객체를 데이터베이스에 저장하기 위해 EntityManager
의 persist
메소드를 사용하여 영속성 컨텍스트에 추가합니다.
이렇게 되면 객체는 영속 상태가 되며, 이후 트랜잭션이 커밋되는 시점에 데이터베이스에 동기화됩니다.
즉 Proxy 객체를 통해 Lazy Loading이 가능해집니다
User user = new User(); // 비영속 상태
entityManager.persist(user); // 영속 상태
더 자세한 내용은 JPA의 Proxy 객체를 참고해주세요
3단계: 영속화
영속화란 객체가 영속성 컨텍스트에 포함되어 있어, 객체의 변경 사항이 데이터베이스에 자동으로 반영되는 상태를 말합니다.
이 상태의 객체는 EntityManager
를 통해 조회할 수 있습니다.
User user = entityManager.find(User.class, userId); // 영속 상태
질문 2: 비영속에서 영속 객체가 된다는 것은 entityManger.persist 하는 순간에 DB에 저장이 된다는 건가?
entityManager.persist
를 호출하면 해당 엔티티 객체는 영속 상태가 됩니다.
하지만 이 시점에 데이터베이스에 즉시 저장되는 것은 아닙니다.
영속 상태가 된 엔티티는 트랜잭션이 커밋되는 시점에 데이터베이스에 저장됩니다.
이를 "트랜잭션을 지원하는 쓰기 지연(Transactional write-behind)"이라고 합니다.
4단계: 1차 캐싱
JPA의 영속성 컨텍스트는 내부에 1차 캐시를 가지고 있습니다.
이 캐시는 같은 트랜잭션 내에서 엔티티를 반복적으로 조회할 때, 데이터베이스에 접근하지 않고 캐시에서 데이터를 가져오므로 성능을 향상시킵니다.
User user1 = entityManager.find(User.class, userId); // 데이터베이스에서 조회
User user2 = entityManager.find(User.class, userId); // 1차 캐시에서 조회
질문 : 1차 캐싱이 있으면 2차 캐싱도 있나?
네, JPA는 2차 캐시(Second Level Cache)를 지원합니다. 1차 캐시는 EntityManager
가 관리하는 영속성 컨텍스트 내에서만 유효하며, 같은 트랜잭션 내에서 엔티티를 반복적으로 조회할 때 사용됩니다.
반면, 2차 캐시는 여러 EntityManager
또는 여러 트랜잭션 간에 공유되는 캐시로, 자주 사용되는 엔티티를 캐싱하여 성능을 향상시키는 데 사용됩니다.
5단계: Dirty Check
Dirty Check는 영속 상태의 객체가 변경될 때, 이 변경 사항을 자동으로 데이터베이스에 반영하는 기능을 말합니다.
이 기능 덕분에 개발자는 엔티티의 변경 사항을 직접 데이터베이스에 반영하는 코드를 작성하지 않아도 됩니다.
User user = entityManager.find(User.class, userId); // 영속 상태
user.setName("John Doe"); // Dirty Check에 의해 자동으로 데이터베이스에 반영됨
질문 : Dirty Check가 왜 dirty하다는 건지? 마지막에 한 번 더 체크를 하는 건가?
Dirty Checking은 Persist Context가 관리하는 엔티티의 상태가 변경되었는지를 확인하는 과정을 말합니다.
"Dirty"라는 용어는 엔티티의 상태가 변경되었음을 의미합니다.
JPA는 트랜잭션이 커밋되는 시점에 Dirty Checking을 수행하여, 상태가 변경된 엔티티를 찾아 데이터베이스에 반영합니다.
부족한 점이나 잘못 된 점을 알려주시면 시정하겠습니다 :>
'DEV > Java' 카테고리의 다른 글
JPA의 영속 상태 (0) | 2023.07.11 |
---|---|
Persist Context (0) | 2023.07.11 |
DataJpaTest (0) | 2023.07.11 |
@ToString (0) | 2023.07.10 |
@Component (0) | 2023.07.10 |