TIL

영속성 관리

영속성 컨텍스트

JPA에서 가장 중요한 2가지

엔티티 매니저 팩토리와 엔티티 매니저

img.png

영속성 컨텍스트

엔티티의 생명주기

img.png

영속성 컨텍스트의 이점

엔티티 조회, 1차 캐시

Member member = new Member();
//1차 캐시에 저장됨
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
Member member = new Member();
member.setId(10L);
member.setName("helloC"); // 여기까지 비영속

em.persist(member); // 영속

Member findMember = em.find(Member.class, 10L); // 조회
System.out.println("findMember.getId()" + findMember.getId());
System.out.println("findMember.getName()" + findMember.getName());

결과 쿼리

findMember.getId() = 10
findMember.getName() = helloC
Hibernate: 
    /* insert hellojpa.Member */ 
        insert 
        into
            Member
            (name, id) 
        values
            (?, ?)

Insert 쿼리가 나가기 전에 엔티티를 조회하고 출력했다. 이는 DB가 아닌 1차 캐시에서 엔티티를 조회했다는 뜻이고 커밋 시점에 insert 쿼리가 나간 것이다. 조회 쿼리는 나가지도 않았다.

영속 엔티티의 동일성 보장

Member a = em.find(Member.class, 10L);
Member b = em.find(Member.class, 10L);
System.out.println(a == b); //동일성 비교 true

엔티티 등록 트랜잭션을 지원하는 쓰기 지연

엔티티 수정 변경 감지 (Dirty Checking)

Member findMember = em.find(Member.class, 2L);
findMember.setName("JPA"); // 변경감지

플러시 (flush)

영속성 컨텍스트의 변경 내용을 데이터베이스에 반영

플러시가 발생하면

영속성 컨텍스트를 플러시하는 방법

em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
// 여기까지 insert 쿼리가 안나갔기 대문에 DB에 아무것도 없음

// 중간에 JPQL 실행, 모든 Member 조회
// 코드 로직 상 memberA, B, C가 조회되어야 함
query = em.createQuery("select m from Member m", Member.class);
List<Member> members= query.getResultList();
// 이런 경우 때문에 JPQL을 실행하면 flush가 강제적으로 일어남

플러시 모드 옵션

em.setFlushMode(FlushModeType.COMMIT)

플러시는!

준영속 상태

// 조회하면 영속 상태 (1차 캐시에 저장)
Member findMember = em.find(Member.class, 2L);
findMember.setName("JPA study"); // 변경감지

// 준영속 상태
em.detach(findMember);

tx.commit(); 
//실행하면 select 쿼리만 나가고 커밋 시 변경 감지로 인한 update 쿼리는 나가지 않는다.