728x90
3.영속성관뢰 - 내부동작방식
- 목차
- 1.영속성 컨텍스트1
- 2.영속성 컨테스트2
- 3.플러시
- 4.준영속상태
- 5.정리
1.영속성 컨텍스트1
- 객체와 관계형 데이터베이스 매핑
- 영속성 컨텍스트
영속성 컨텍스트
- 엔티티를 영구 저장하는 환경
EntityManager.persist(entity)
- persist 는 DB 에 저장이 아닌 영속성 컨텍스트에 저장한다
- 논리적인 개념 , 눈에 보이지 않는다 , 엔티티 매니저를 통해서 접근
영속성 컨텍스트
- 비영속 : 새로운 상태
- 영속 : 관리하는 상태
- 준영속 : 분리된 상태
- 삭제 : 삭제된 상태
비영속성 상태
- 객체를 생성한 상태
Member member = new Member();
member.setId("memberId");
member.setUsername("회원");
영속성 상태
- 객체를 저장한 상태
em.persist(member)
비영속,영속
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
//비영속
Member member = new Member();
member.setId(100L);
member.setName("HelloJpa");
//영속
em.persist(member);
tx.commit();
}catch (Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
- DB 는 tx.commit() 시점에서 쿼리가 날아간다
준영속 상태
- 영속성 컨텍스트에서 분리
em.detach(member)
삭제 상태
- 객체를 삭제한 상태
em.remove(member)
영속성 컨텍스트 이점
- 1차캐시
- 동일성
- 트랜잭션을 지원하는 쓰기 지연
- 변경감지
- 지연로딩
2.영속성 컨테스트2
1차 캐시
- 영속성 컨텍스트는 조회할때 1차캐시를 찾아본다
- 1차캐시에 값이 있으면 반환
- 영속성 컨텍스트는 조회할때 1차캐시를 찾아본다
- 1차캐시에 값이 없으면 DB 에서 조회한다음 가져와서 1차캐시에 저장하고 반환한다
영속 엔티티의 동일성 보장
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
System.out.println("result = " + (findMember1==findMember2));
tx.commit();
}catch (Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
- 조회는 1번만 된다
- findMember1==findMember2 결과값은 true
엔티티 등록할때 트랜잭션을 지원하는 쓰기 지연가능
- 1차캐시 -> 쓰기지연 SQL 저장소 -> 트랙재션 커밋됨 -> Insert 문 나간다
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Member member1 = new Member(150L, "A");
Member member2 = new Member(160L, "B");
em.persist(member1);
em.persist(member2);
System.out.println("=====================");
tx.commit();
}catch (Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
- persist 되도 쓰기지연 sql 저장소에 보관
- tx.commit() 되는 순간 Insert SQL 문이 날아간다
변경감지
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Member member = em.find(Member.class, 150L);
member.setName("hello");
System.out.println("=====================");
tx.commit();
}catch (Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
- 1차캐시에서 조회 한다
- tx.commit 되면서 Update 문이 나간다
- JPA 는 변경을 감지해줘서 Update 해준다 (더티체킹)
- tx.commit 되기전에 flush 가 일어난다
- flush 를 통해서 엔티티와 스냅샷을 비교
- 스냅샷 - 최초의 영속성 컨텍스트 값
- 변경된 부분을 쓰기지연 SQL 문 저장소에 Update 해준다
- 실제 DB 에 Update 된다
3.플러시
- 영속성 컨텍스트의 변경내용을 데이터베이스에 반영
- 변경감지 -> 쓰기지연 sql 저장소에 등록 -> DB 에 전송
- em.flush , 트랜잭션 커밋 , JPQL 실행
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Member member = new Member(200L, "member200");
em.persist(member);
em.flush();
System.out.println("=====================");
tx.commit();
}catch (Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
- 결과를 보면 트랜잭션 커밋하기 전에 Insert 문이 들어갔다
- flush 되도 1차캐시는 안지워 진다
JPQL 쿼리 실행시 플러시가 자동으로 호출되는이유
- JPQL 은 DB 에서 가져와야 실행된다
- 무조건 flush 를 쓰고 가져온다
플러시 정리
- 영속성 컨텍스트를 비우지 않음
- 변경내용을 데이터베이스에 동기화
- 트잰잭션이라는 작업단위 - 커밋직전에만 동기화 하면된다.
4.준영속상태
- 영속 -> 준영속
- 영속 상태의 엔티티가 영속성 컨텍스트에서 분리
- 영속성 컨텍스트가 제공하는 기능을 사용못함
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Member member = em.find(Member.class, 150L);
member.setName("hello hello");
em.detach(member);
System.out.println("=====================");
tx.commit();
}catch (Exception e){
tx.rollback();
}finally {
em.close();
}
emf.close();
}
}
- em.detach(member) 을 이용해서 준영속 제거
- 변경을 감지했지만 Update 문이 안나가것을 확인할수 있다
- em.detach - > 특정 엔티티 만 준영속
- em.clear -> 모두 초기화
- em.close -> 영속성 컨텍스트를 종료
참고
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard
728x90
'Back-End > Spring Data' 카테고리의 다른 글
4.엔티티 매핑 (0) | 2021.01.07 |
---|---|
2.JPA 시작하기 (0) | 2021.01.04 |
1.JPA 소개 (0) | 2021.01.04 |
9.웹 계층 개발 2(주문) (0) | 2021.01.01 |
8.변경감지 와 병합 (0) | 2021.01.01 |