※ 본문은 김영한 선생님의 인프런 '자바 ORM 표준 JPA 프로그래밍 - 기본편' 강의를 듣고 정리한 내용임을 알립니다.
★ JPA에서 가장 중요한 2가지
- 객체와 관계형 데이터베이스 매핑하기 (Object Relational Mapping)
- 영속성 컨텍스트
▶ 영속성 컨텍스트
- JPA를 이해하는 데에 있어서 가장 중요한 용어!
- "Entity를 영구 저장하는 환경"
- 논리적 개념으로써, 눈에 보이지 않음
- EntityManager를 통해서 영속성 컨텍스트에 접근할 수 있음
★ entityManager.persist(entity); → 사실 entity를 DB에 저장하는 것이 아니라, 영속성 컨텍스트에 저장하는 것!
※ Entity의 생명주기
- 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
└> Member member = new Member();
- 영속 (managed) : 영속성 컨텍스트에 관리되는 상태
└> em.persist(member);
- 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태
└> em.detached(member);
- 삭제 (removed) : 객체를 삭제한 상태
└> em.remove(member);
▶ 영속성 컨텍스트의 이점
- 1차 캐시에서 조회
└> Member findMember = em.find(Member.class, "member1"); → DB를 바로 찾지 않고 영속성 컨텍스트를 먼저 조회
└> 1차 캐시에 없을 경우 DB에서 조회하며, 이 때 조회한 값은 1차 캐시에 저장 및 조회값 반환
※ 1차 캐시는 한 트랜잭션 안에서만 이루어지기 때문에 성능에 이점은 크지 않지만 비즈니스 로직에 도움을 준다.
- 영속 엔티티의 동일성 보장
└> 같은 트랜잭션 안에서 동일한 대상에 대해 조회한 값은 동일한 값을 가짐
- 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(memberA);
em.persist(memberB);
transaction.commit();
=> commit이 있기 전에는 INSERT SQL을 DB에 보내지 않는다.
=> persist는 1차 캐시에 객체를 저장하기도 하고, 쓰기 지연 SQL 저장소에도 INSERT SQL을 미리 작성해놓는다.
※ 역시 이점은 그렇게 크지 않다.
- 변경 감지 (Dirty Checking)
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
Member memberA = em.find(Member.class, "memberA");
memberA.setUsername("로코");
memberA.setAge(20);
transaction.commit();
=> em.persist나 em.update 같은 별도의 코드가 없어도 변경사항을 자동으로 감지한다.
=> 값을 최초로 읽어올 때 스냅샷에 저장해두고, 값이 변경되고 커밋했을 때 JPA가 Entity와 스냅샷을 비교하는 방식
▶ flush
: 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영
→ flush가 발생하면?
└> 변경 감지(Dirty Checking) → 수정된 엔티티를 쓰기 지연 SQL 저장소에 등록 → 쿼리들을 DB에 전송
→ 영속성 컨텍스트를 flush하는 방법
- em.flush() - 직접 호출 (테스트하는 경우에 사용)
- 트랜잭션 커밋 - flush 자동 호출
- JPQL 쿼리 실행 - flush 자동 호출
★ flush는 영속성 컨텍스트를 비우는 것이 아닌, 변경 내용을 DB에 동기화하는 것!
★ 트랜잭션이라는 작업 단위에서 커밋 직전에만 동기화하는 매커니즘
▶ 준영속 상태
: 영속 상태의 Entity가 영속성 컨텍스트에서 분리된(detached) 상태
→ 영속성 컨텍스트가 제공하는 기능을 사용하지 못하게 됨
→ 준영속 상태로 만드는 방법
- em.detached(entity) - 특정 Entity만 준영속 상태로 전환
- em.clear() - 영속성 컨텍스트 완전 초기화
- em.close() - 영속성 컨텍스트 종료
'JVM > JPA' 카테고리의 다른 글
객체지향 쿼리 언어 (JPQL) (0) | 2021.04.18 |
---|---|
값 타입 (0) | 2021.04.16 |
Proxy와 연관관계 관리 (0) | 2021.04.16 |
Entity Mapping (0) | 2021.04.15 |
JPA란? (0) | 2021.04.10 |