영속성 컨텍스트란?
- 엔티티를 영구 저장하는 환경
- 엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다
em.persist(member)
엔티티 매니저를 사용해 회원 엔티티를 영속성 컨텍스트에 저장한다
엔티티 생명주기
- 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태
- 영속 (managed) : 영속성 컨텍스트에 저장 된 상태
- 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리 된 상태
- 삭제 (remove) : 삭제된 상태
비영속
Member member = new member();
member.setId("member1");
member.setUserName("회원1");
영속
- 엔티티 매니저를 통해 엔티티를 영속성 컨텍스트에 저장
- 영속성 컨텍스트에 의해 관리되는 상태
em.persist(member);
준영속
- 영속상태의 엔티티를 관리하지 않게되면 준영속 상태이다
em.detach(member);
em.close();
em.clear();
삭제
- 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한다
em.remove(member);
영속성 컨텍스트의 특징
- 영속성 컨텍스트는 엔티티를 식별자값으로 구분한다 영속상태는 식별자 값이 반드시 있어야 한다
- 영속성 컨텍스트가 엔티티를 관리하면 다음과 같은 장점이 있다
- 1차캐시
- 동일성보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩
1차캐시
- 영속성 컨텍스트는 내부에 캐시를 가지고 있는데 이것을 1차 캐시라 한다
- 영속 상태의 엔티티는 모두 이곳에 저장된다
- 1차 캐시의 키는 @Id로 매핑한 식별자이며 값은 엔티티 인스턴스이다
- 영속 되어있는 상태에서 다음과 같이 하면 조회가 가능하다
Member member = em.find(Member.class, "member1");
- 1차 캐시에서 member1를 찾는다
- 없다면 데이터베이스에서 조회한다
- 조회한 데이터를 1차 캐시에 저장한다 ( 엔티티에 영속상태로 만듬 )
- 조회한 엔티티를 반환한다
동일성 보장
member a = em.find(Member.class, "member1");
member b = em.find(Member.class, "member1");
System.out.println(a==b);
- 반복 호출을 해도 영속성 컨텍스트는 1차 캐시에 있는 같은 인스턴스를 반환한다
쓰기 지연
- 엔티티 메니저는 트랜잭션을 commit 하기 전까지 데이터베이스에 엔티티를 저장하지 않고 내부 쿼리 저장소에 INSERT SQL을 모아두고 트랜잭션을 커밋할때 데이터베이스에 보내게 되는것을
쓰기 지연이라고 한다
변경감지 (dirty checking)
- 엔티티를 수정할때는 단순히 엔티티를 조회해서 데이터만 변경하면 된다
- 엔티티의 변경사항을 데이터베이스에 자동으로 반영하는 기능
Member memberA = em.find(Member.class, "memberA")
memberA.setUserName("홍길동");
transaction.commit();
- 트랜잭션을 커밋하면 엔티티 매니저 내부에서 플러시가 호출된다
- 엔티티와 스냅샷을 비교해서 변경된 엔티티를 찾는다
- 변경된 엔티티가 있으면 수정쿼리를 생성해 쓰기지연 SQL 저장소에 보낸다
- 쓰기 지연 저장소의 SQL을 데이터 베이스에 보낸다
- 데이터베이스 트랜잭션을 커밋한다
지연로딩
- 연관 관계 매핑이 되어있는 엔티티를 조회할때 조회 시점에는 연관된 엔티티를 실제 객체 대신 프록시 객체로 로딩
- 연관된 매핑 엔티티의 해당 객체를 실제 사용할때 영속성 컨텍스트를 통해 데이터를 불러온다.
참조
자바 ORM 표준 JPA 프로그래밍
JPA-영속성-컨텍스트란
@Transactional 사용과 영속성 컨텍스트(persistence context)