영속성 컨텍스트

- 엔티티를 영구 저장하는 환경

- 영속성 컨텍스트는 논리적인 개념으로 눈에 보이지 않음

- 엔티티 매니저를 통해 영속성 컨텍스트에 접근

 

 

생명주기

비영속(new)

영속성 컨텍스트와 관계 없는 상태

Member member = new Member();
member.setId("m1");
member.setUsername("");

영속(managed)

영속성 컨텍스트에 저장된 상태

Member member = new Member();
member.setId("m1");
member.setUsername("");

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(member);

준영속(detached)

영속성 컨텍스트에 저장되었다가 분리된 상태

em.detach(member);

삭제(delete)

영속성 컨텍스트와 DB에서 삭제된 상태

em.remove(member);

 

영속성 컨텍스트가 제공하는 이점

1. JPA 의 조회시 캐시 기능

em.find(Member.class, "m1");

영속 컨텍스트(entityManager)(1차 캐시) 에서 먼저 조회

(영속 컨텍스트에 존재하지 않을시 DB에서 조회 후 영속 컨텍스트에 저장, 그리고 반환)

 

2. 영속 엔티티의 동일성 보장

Member a = em.find(Member.class, "m1");

Member b = em.find(Member.class, "m1");

System.out.println(a==b); //true

1차 캐시로 반복 가능한 읽기(REPEATABLE READ)등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공

 

 

3. 트랜잭션을 지원하는 쓰기 지원

em.persist(member); //쓰기지연 SQL 저장소, 1차 캐시에 저장

flush / commit 시 DB에 insert 쿼리를 보낸다.

 

4. 엔티티 수정시 변경 감지

Member memberA = em.find(Member.class, "m1");
memberA.setUserName("pyo");
memberA.setAge(10);

em.update(memberA); 와 같은 코드가 필요없다.

transaction.commit;

flush/commit 시점에 스냅샷을 확인하여 바뀐 값이 존재시 update 쿼리를 DB에 보낸다.

collection framework list 에서 값을 변경 후 list 에 값을 다시 넣어주지 않아도 list 값이 바뀌는 것과 마찬가지로

update 를 직접 해줄 필요가 없다.

 

JPQL 쿼리 실행시 flush가 자동으로 호출된다.

아래와 같이 flush 및 commit을 직접적으로 해주지 않을 경우 query 로 조회된 결과가 나오지 않으므로

이같은 실수를 방지하기 위해  JPQL 쿼리 실행시 flush 자동으로 호출.

em.persist(memberA);
em.persist(memberB);

query = em.createQuery("select m from Member m", member.class);
List<Member> members = query.getResultList();

flush 는 영속성 컨텍스트를 비우는게 아닌, 영속성 컨텍스트의 변경내용을 DB에 동기화

트랜잭션 작업단위가 중요. 커밋 직전에만 동기화 하면 된다.

 

준영속 상태로 만드는 방법

em.detach(memberA) 특정 엔티티만 준영속 상태로 전환

em.clear() 영속성 컨텍스트 초기화

em.close() 영속성 컨텍스트 종료

 

 

반응형

+ Recent posts