JPA에서 핵심적인 내용은 다음과 같다.
- 객체와 관계형 데이터베이스 매핑(ORM, Object Relational Mapping)
- 영속성 컨텍스트
우선, 영속성 컨텍스트에 대해 알아보자.
엔티티 매니저와 팩토리와 엔티티 매니저
먼저, 웹 애플리케이션에서 EntityManagerFactory와 EntityManager의 간단한 동작을 살펴보았다.
클라이언트 요청을 받으면 EntityManagerFactory는 각 클라이언트에게 EntityManager를 부여한다.
각 클라이언트는 부여받은 EntityManager를 가지고 DB에 접근한다.
영속성 컨텍스트
JPA를 이해하는데 가장 핵심적이며, "엔티티를 영구 저장하는 환경"이라는 뜻을 가지고 있다.
실제 코드에서는 EntityManager.persists(entity)와 같이 사용한다.
(entity)는 객체이다.
영속성 컨텍스트는 논리적인 개념이며, 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.
엔티티의 생명주기
비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계없는 새로운 상태
영속 (managed) : 영속성 컨텍스트에 관리되는 상태
준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
삭제 (removed) : 삭제된 상태
비영속
//객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
영속
//객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
//객체를 저장한 상태(영속)
em.persist(member);
준영속, 삭제
//회원 엔터티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);
//객체를 삭제한 상태(삭제)
em.remove
영속성 컨텍스트의 이점
1차 캐시를 사용하며, 동일성(identity)를 보장한다.
트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
변경 감지(Dirty Checking), 지연 로딩(Lazy Loading)
엔티티 조회, 1차 캐시
//엔티티를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//엔티티를 영속
em.persist(member);
1차캐시에서 조회
@Id로 지정한 키 값을 통해 Entity인 member 객체를 조회한다.
데이터베이스에서 조회
Member findMember2 = em.find(Member.class, "member2");
1차적으로 JPA는 데이터를 먼저 1차 캐시에서 찾는다. 만약 1차 캐시에 찾고자 하는 데이터가 존재한다면 그대로 객체를 반환한다. 존재하지 않는다면 DB를 조회한다. DB 조회 후, 객체를 1차 캐시에 저장하고 객체를 반환한다.
영속 엔티티의 동일성 보장
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
a 객체와 b 객체는 같은 객체이다.
1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.
엔티티 등록 - 트랜잭션을 지원하는 쓰기 지연
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
//엔티티 매니저는 데이터 변경 시 트랜잭션을 시작한다.
tx.begin(); // 트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT 쿼리를 DB에 보내지 않는다.
//커밋과 동시에 순간 데이터베이스에서 insert SQL를 보낸다. flush가 쿼리를 보내는데, 커밋과 동시에 자동으로 호출된다.
tx.commit();
'JPA' 카테고리의 다른 글
[JPA] 연관관계 매핑 - 객체지향 모델링 단방향 매핑 (0) | 2023.04.04 |
---|---|
[JPA] 엔티티 매핑 - 기본 키 매핑 (0) | 2023.02.26 |
[JPA] 엔티티 매핑 - 객체와 테이블 매핑, 필드와 컬럼 매핑 (0) | 2023.02.26 |
[JPA] 변경감지와 플러시 (0) | 2023.02.24 |
[JPA] JPA 기초, 구동방식 (0) | 2023.02.24 |