영속성 컨텍스트 1
영속성 컨섹스트
EntityManager.persist(entity);
// DB에 저장하는게 아니라 entity를 영속성 컨텍스트라는 곳에 저장하는 것이다.
// 영속성 컨텍스트는 논리적 개념으로 눈에 보이지 않기 때문에, EM을 통해서 접근한다.
엔티티의 생명주기
// 비영속
Member member = new Member();
member.setId(100L);
member.setName("HelloJPA");
// 영속
em.persist(member); // persist가 아닌 commit 하기 전에 쿼리를 날린다.
영속성 컨텍스트 2
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//1차 캐시에 저장됨
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
//find("member2")의 경우 1차캐시에 없기 때문에 DB에서 조회하여 1차캐시에 저장 후 반환
//-> 1차 캐시에 저장 ? = 영속 상태로 등록
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
System.out.println(a == b); //동일성 비교 true
// 1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을
// 데이터베이스가 아닌 애플리케이션 차원에서 제공
-> 쉽게 생각하면, 동일한 트랜잭션에서 실행하면 == 비교시 true
em.persist(member1);
em.persist(member2);
System.out.println("=======================");
tx.commit();
버퍼링을 모아서 write 하는 이점을 얻을 수 있다
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
//em.update(member) 이런 코드가 있어야 하지 않을까?
transaction.commit(); // [트랜잭션] 커밋
스냅샷과 비교하여 새로운 쿼리를 생성하여 UPDATE 한다
(값이 이전과 같거나 달라도 모두 쿼리를 전달, if 문 같은것을 사용 할 필요 x)
플러시
쌓아놨던 SQL 문을 DB에 날린다
즉, 영속성 컨텍스트의 변경 내역들을 DB에 전달한다
(flush가 발생한다고 해서 DB 트랜잭션에 커밋되는것은 아니다)
플러시 방법 (알아만 놓기)
플러시는 1차캐시는 건드리지 않고, (영속성 컨텍스트를 비우지 않음) (1차캐시에 올라간 상태 = 영속 상태)
쓰기 지연 SQL 저장소에 있는것과 변경 감지된 UPDATE 쿼리들이 쌓인것들을 DB에 반영하는 과정이다.
-> 트랜잭션이라는 작업단위가 중요하기 때문에 커밋 직전에만 동기화를 하면 된다
준영속 상태
지금 이해하기는 쉽지않고 실전에서 (웹 애플리케이션 개발)
Reference
김영한 님 - 자바 ORM 표준 JPA 프로그래밍 - 기본편