[JPA] JPQL과 영속성 컨텍스트 2
영속성 컨텍스트의 이점
1) 1차 캐시
2) 동일성(identity) 보장
3) 트랜잭션을 지원하는 쓰기 지연 (transactional write-behind)
4) 변경 감지 (Dirty Checking)
5) 지연 로딩
엔티티 조회, 1차 캐시
//객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("멤버1");
member.setUserName("회원1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
//객체를 저장한 상태(영속)
em.persist(member);
- 키가 pk로 등록한 값이 되고 value가 객체가 된다.
1차 캐시에서의 조회
- DB를 찾아보는게 아니라 캐시를 조회먼저해서 가져온다.
데이터 베이스에서의 조회
- find(“member2”) - > 1차 캐시에 없음
- DB 조회
- 1차 캐시에 저장을 한다.
- member2 반환
- 이후 member2를 조회하면 1차캐시에서 가져온다
하지만, 엔티티 매니저는 DB 트랜잭션 단위로 만들고 트랜잭션이 끝나면 종료시키는데 고객의 요청이 끝나면 지우기 때문에 1차캐시도 이때 날라간다.
1차 캐시 저장되고, 그 이후 조회를 하기때문에 select 쿼리가 로그로 남지 않았다.
영속 엔티티의 동일성 보장
//비영속
Member member = new Member();
member.setId(101L);
member.setName("HelloJPA");
//영속
System.out.println("=====BEFORE=====");
em.persist(member);
System.out.println("=====AFTER=====");
Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
System.out.println(findMember1 == findMember2) // true 반환함!
tx.commit();
true 이유 : 1차캐시가 있기때문에 반복가능한 읽기를 애플리케이션 차원에서 제공한다.
엔티티등록 트랜잭션을 지원하는 쓰기 지연
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야한다.
transaction.begin(); // 트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 Insert SQL을 데이터베이스에 보내지않는다.!!
//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // 트랜잭션 커밋
- 멤버A가 일단 1차 캐시에 들어감과 동시에 JPA가 엔티티를 분석해서 SQL 생성하고 쓰기지연 SQL 저장소에 저장해둠
- 멤버B도 똑같이 동작하고 쓰기 지연 SQL 저장소에 쌓아둔다.
- 트랜잭션을 커밋하는 시점에 flush가 되면서 날라간다.
변경 감지
값만 바꾸고, JPA에게 업데이트 쿼리를 날려달라고 한게없는데 변경된 것을 확인 할 수있다.
변경감지 동작
-
- flush()
-
- 엔티티와 스냅샷 (내가 값을 읽어온 최초시점의 상태를 떠놓는것 )과 비교
-
- Update SQL 생성
-
- flush 후 commit 됨
Flush
영속성 컨텍스트의 변경내용을 데이터베이스에 반영하는 것
플러시 발생시
- 변경감지 일어난다.
- 수정된 엔티티 쓰기 지연 SQL 저장소에 등록
- 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송 (등록, 수정, 삭제 쿼리)
영속성 컨텍스트를 플러시하는 방법
- em.flush() - 직접 호출
- 트랜잭션 커밋 - 플러시 자동 호출
- JPQL 쿼리 실행 - 플러시 자동 호출
😄 참고 : 인프런 김영한님의 JPA 기본 강의 및 교재 , 블로그
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
개인메모