JPA/JPA 기본

7. 영속성 컨텍스트 2

sdafdq 2023. 10. 20. 08:21
Member member= new Member();
member.serId("member1");
member.setUsername("회원1");

em.persist(member);

저렇게 EntityManager 내부에 있는 영속 컨텍스트에 EntityManager를 통해 persist로 영속화 시키면,

저렇게 키가 id, Entity가 그 객체가 된 상태로 영속 컨텏트에 저장된다. 이것이 캐싱이다.

 

이렇게 하면 이점이,

Member findedMember = em.find(Member.class, 1L);

이렇게 조회 시에,

먼저 캐싱된 거에 있는지 id로 조회해본다.

그럼 DB를 안거치기 때문에 성능이점이 있다.

없으면 DB에서 조회해 온 다음, 또 그걸 영속성 컨텍스트에 저장시켜 캐싱한다.

(참고로, 1차캐시는 한 트랜잭션 단위의 캐시, 2차캐시는 애플리케이션 전체가 공유하는)

 

            Member member = new Member();
            member.setId(101L);
            member.setName("HelloJPA");

            em.persist(member);

            Member findedMember = em.find(Member.class,101L);
            System.out.println("findedMember is same member = " + (findedMember == member));

이거 실제로 주소값이 같아 true가 나온다. (동일성 보장)

또, 먼저 1차 캐시에 있는지 조회해서 나오면 그걸 그대로 반환하기 때문에 DB에 조회 쿼리문도 날리지 않았다.

 

EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();

tx.begin();

Member findedMember1 = em.find(Member.class,101L);
Member findedMember2 = em.find(Member.class,101L);

System.out.println("findedMember is same member = " + (findedMember1 == findedMember2));

얘도 첫번째 조회할 때는 1차캐시가 비어있어서 DB에 쿼리문을 날려 DB로부터 가져온 다음 영속성 컨텍스트에 넣어놓고 반환해 주지만, 

두번째 조회할 때는 1차 캐시에서 조회해 DB에 쿼리를 날리지 않았다.

 

JPA는 조회하면 무조건 영속성 컨텍스트에 올려 놓음

 

 

 

쓰기 지연이 보장됨.

EntityManager.persist(memberA);
EntityManager.persist(memberB);

tx.commit();

저렇게 persist 하면 영속성 컨텍스트에 등록하는 거라고 했다.

즉, DB에 SQL문 날리는 게 아니다.

먼저 persist 하면 영속성 컨텍스트에 등록한다.

 

commit()하는 순간,

실제 DB에 commit 쿼리 이전에 영속성 컨텍스트에 적용된 내용들을 반영하여 쿼리를 만들고,

그 쿼리와 같이 commit 순간에 commit 쿼리와 함께 날리는 것 같다.

 

즉, commit()하면 영속성 컨텍스트에 있는 내용들을 반영하여 쿼리를 만들고, 그 뒤에 commit 쿼리를 붙여 같이 날리는 모양이다.

 

그러므로, 쓰기 지연이 보장된다.

그래서 쿼리를 한번에 날려서, 성능적 이점이 있다.

이거를 batch 기능인가 그렇게 부른다. 유니티 개발하면서 한번 경험해 봤던 기능이긴 하다. 화면상에 

commit() 하면,

쓰기 지연 SQL 저장소를 DB에 전송하는 게 flush고,

그 후 비로소 commit 함.

 

 

 

 

변경

Member member = em.find(Member.class, 150L);
member.setName("ZZZZZ");

그냥 이렇게 해 주면 변경임. 

맨 처음 엔티티가 영속성 컨텍스트에 들어왔을 때 그것의 초기값을 스냅샷으로  찍어두고, 

나중에 commit시점에 더티채킹이라고, 변경된거 있는지 확인해보고 변경된 거 있으면 update문 만들어서 그것도 쓰기 지연 SQL 저장소에 담아두고 commit이랑 같이 DB에 날림

 

 

 

 

삭제

Member member = em.find(Member.class, 150L);
em.remove(member);

삭제도 똑같이 commit 시점에 

이것도 스냅샷이랑 그럼 비교하는 건가? 삭제되었다고 어떻게 표시하는거지. 그냥 마크? 뭐 솔직히 방법이 너무 많아서 잘 모르겠음. 어려운 것도 아니라 굉장히 많은 방법으로 효율적이게 할 수 있음.

 

여튼 삭제도 commit시점에 쿼리가 나간다고 함.

 

 

'JPA > JPA 기본' 카테고리의 다른 글

9. 준영속 상태  (0) 2023.10.20
8. 플러시  (0) 2023.10.20
6. 영속성 컨텍스트  (0) 2023.10.20
5. 개발  (0) 2023.10.19
4. 프로젝트 생성  (0) 2023.10.19