Web/JAVA
[JPA] 영속성 컨텍스트
부에나온다
2024. 3. 20. 16:21
1. 영속성 컨텍스트
- ORM은 객체와 데이터베이스 테이블의 맵핑을 통해 엔티티 클래스 객체안에 포함된 정보를 테이블에 저장하는 기술
- JPA에서는 엔티티 객체 정보를 영속성 컨텍스트를 통해 어플리케이션 내에서 오래 지속되도록 보관한다.
- Server side와 Database 사이에 엔티티를 저장하는 논리적인 영역이라고 할 수 있다. 엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.
- 영속성 컨텍스트는 엔티티 매니저(Session)를 생성할 때 하나 만들어진다. 그리고 엔티티 매니저(Session)을 통해서 영속성 컨텍스트에 접근할 수 있고 영속성 컨텍스트를 관리할 수 있다.
- EntityManagerFactory : EntityManager를 생성한다. 불변객체로 Thread-Safe 하다. 싱글톤패턴으로 재활용이 가능하다.
- EntityManager : 영속성 컨텍스트(가상 데이터베이스)를 관리하는 객체
2. 엔티티의 생명주기
- 비영속 : 엔티티 객체를 생성했다. 현재 순수한 상태로 아직 저장하지 않은 단계.
// 객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
- 영속 : 엔티티 매니저를 통해서 엔티티를 영속성 컨텍스트에 저장(persist())했다. 이렇게 영속성 컨텍스트가 관리하는 엔티티를 영속상태라고 부른다.
Member member = new Member();
member.setId("member1");
member.setUsername("홍길동");
// 객체를 영속성 컨텍스트에 저장(영속)
em.persist(member);
- 준영속 : 영속성 컨텍스트가 관리하던 영속 상태의 엔티티를 영속성 컨텍스트가 관리하지 않으면 준영속 상태 detach() 하면 관련이 없어진다.
em.detach(member); // 엔티티를 영속성 컨텍스트에서 분리
em.claer(); // 영속성 콘텍스트를 비움
em.close(); // 영속성 콘텍스트를 종료
- 삭제 : 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다.
// 객체를 삭제한 상태(삭제)
em.remove(member);
3. 영속성 컨텍스트의 장점
1차 캐시
- 영속 상태의 Entity는 모두 영속성 컨텍스트에 HashMap(key(@Id) = value(Entity)) 로 저장된다.
- 따라서 식별자 (@Id)가 반드시 있어야 한다.
Member member = new Member();
member.setId("member1"); // 직접 id 값을 초기화 암으로써 준영속상태로 인지한다.
member.seUsername("회원1");
// 엔티티 영속(1차 캐시 저장)
em.persist(member);
// 1차 캐시에서 조회
em.find(Member.class, "member1");
- 아직 flush가 일어나지 않아 1차 캐시에 저장된다. 추후 flush를 통해 db 저장된다.
- 만약에 1차 캐시에 없으면 db 조회 후 1차 캐시에 저장한 후 반환한다.
- 보통 entityManager는 transaction 단위로 만들고 종료되므로 em 종료시 캐시도 날라간다.
- 순간적인 성능 이점보다는 비즈니스 로직이 굉장히 복잡할때 좋다.
동일성 보장
- 1차 캐시가 있기 때문에 영속 엔티티의 동일성(메모리 주소가 같음을 의미)을 보장해 준다.
- 1차 캐시로 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 db가 아닌 어플리케이션 차원에서 제공한다.
트랜잭션으로 인한 쓰기 지연
- 쓰기 지연 SQL 저장소가 존재한다.
- entity 분석 후 insert 쿼리를 생성하고 쓰기 지연 SQL 저장소에 쌓는다.
- commit 하는 순간 쿼리들이 flush 되면서 db로 날아간다.
- 즉, 트랜잭션이 끝나야 Commit이 이루어지고 반영된다.
변경 감지(dirty checking)
- em.update 와 같은 코드를 작성하지 않는다.
- flush 발생 시 entity와 스냅샵을 비교한다. 스냅샷을 처음 db에서 읽어왔을때 내용이다.
- 바뀐내용이 있으면 쓰기 지연 SQL 저장소에서 update 쿼리를 작성하여 commit 시 db에 적용한다.