JAVA/JPA

영속성 컨텍스트

gracelove91 2020. 1. 16. 18:59

영속성 컨텍스트

EntityManagerFactory에서 고객의 요청이 있을 마다 EntityManager를 생성한다. 이렇게 생성된 EntityManager는 커넥션풀에서 커넥션을 가져와 사용한다.

EntityManagerFactory는 어플리케이션 통틀어서 단 하나!
EntityManager는 쓰레드간 공유하면 안된다.

영속성 컨텍스트

  • "엔티티를 영구 저장"하는 환경이라는 뜻.
    • EntityManager.persist(entity)
      • entity를 DB에 저장하는 것이 아니라, 영속성컨텍스트에 저장한다.
  • 엔티티 매니저를 통해 영속성컨텍스트에 접근한다.
  • 트랜잭션이 끝나면 영속컨텍스트 또한 종료된다.

엔티티의 생명주기

  • 비영속(new / transient)
    • 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
  • 영속(managed)
    • 영속성 컨텍스트에 관리되는 상태
  • 준영속(detached)
    • 영속성컨텍스트에 저장되었다가 분리된 상태
  • 삭제(removed)
    • 삭제된 상태

비영속

// 객체를 생성한 상태(비영속)
Member member = new Member();
member.setId(1L);
member.setName("memberA");

영속

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

tx.begin();
em.persist(member) 
- 객체를 저장한 상태(영속). 디비에 저장된 상태 아니다. 
- 트랜잭션이 커밋돼야 디비에 저장된다.

준영속

em.detach(member); //영속상태인 member를 영속성컨텍스트에서 분리했다.

삭제

em.remove(member); // 객체를 삭제한 상태.

영속성 컨텍스트의 장점

  • 1차캐시
    • persist하면 1차캐시에 먼저 저장.
    • find를 하면 DB에 바로 접근하는 것이 아닌, 1차캐시에서 먼저 찾는다.
      • 만약 1차캐시에 없으면 그제서야 DB에 접근해서 조회하게 되는데, 조회결과값을 1차캐시에 저장하고 반환한다.
        Member member = new Member();
        member.setId(2L);
        member.setName("memberB");
        

em.persist(member);

Member findMember = em.find(Member.class, 2L);
System.out.println("findMember = " + findMember.getName());

    - `SELECT` 쿼리 안나간다! 왜? 1차캐시에 있기때문에
- 동일성 보장
    - 같은 트랜잭션 안이어야 함.
````java
Member findMember1 = em.find(Member.class, 2L);
Member findMember2 = em.find(Member.class, 2L)l
System.out.println(member1 == member2) //true
  • 트랜잭션을 지원하는 쓰기 지연
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    
    

//persist하면 1차캐시에 저장함과 동시에,
//영속성 컨텍스트의 쓰기지연SQL저장소에 INSERT SQL저장
em.persist(memberA);
em.persist(memberB);

//커밋하는 순간 Insert SQL 보낸다.
tx.commit();

- 변경감지(더티체킹)
    - 영속상태인 객체를 변경했다면 커밋시점에 변경됨.(persist 호출 불필요)
- 지연로딩