JPA에서 가장 중요한 2가지!
영속성 컨텍스트를 이해하면 JPA 내부 동작 방식을 알 수 있다.
영속성 컨텍스트는 엔티티를 영구 저장하는 환경
이라는 뜻!
영속성 컨텍스트는 논리적 개념이며, EntityManager를 통해 영속성 컨텍스트에 접근한다.
EntityManager.persist(entity);
// 객체만 생성된 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
새로운
상태// 객체만 생성된 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 객체를 저장한 상태 (영속)
em.persist(member);
관리
되는 상태가 된다.// 영속성 컨텍스트에 저장된 객체를 분리, 준영속 상태
em.detach(member);
// 객체를 삭제한 상태 (삭제)
em.remove(member);
영속성 컨텍스트의 사용으로 얻을 수 있는 5가지 이점이 있다.
영속성 컨텍스트 내부에 1차 캐시라는 것이 존재한다.
// 객체만 생성된 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
// 객체를 저장한 상태 (영속)
em.persist(member);
영속성 컨텍스트에 저장된 객체를 가져올 땐(조회) 어떤 일이 벌어질까?
영속성 컨텍스트에 저장된 객체를 가져올 땐 바로 DB를 조회하지 않고, 1차 캐시에 해당 객체가 있는지 먼저 조회해보고, 없다면 DB에서 찾는다
1차 캐시에 저장된 객체를 조회하는 경우)
// 객체만 생성된 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
// 객체를 저장한 상태 (영속), 1차 캐시에 저장
em.persist(member);
// 1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
1차 캐시에 저장되지 않은 객체를 조회하는 경우)
// 1차 캐시에 없으므로, DB에서 조회한다.
Member findMember = em.find(Member.class, "member2");
Member a = em.find(Member.class, "member1");
Member b = em.find(Member.class, "member1");
// 동일성 비교
System.out.println(a == b);
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction()
tx.begin(); // 트랜잭션 시작
// 영속, 1차 캐시에 저장
em.persist(memberA);
em.persist(memberB);
// 객체가 1차 캐시에 저장된 상태, 아직 DB에 INSERT 쿼리 날리지 않음
// 트랜잭션 커밋, 커밋하는 순간 DB에 INSERT 쿼리를 날린다.
tx.commit();
쓰기 지연 SQL 저장소
에 INSERT 쿼리가 쌓인다.em.persist(memberA);
했을 때 일어나는 일)
em.persist(memberB);
했을 때 일어나는 일)
tx.commit();
했을 때 일어나는 일)
persist()시 마다 쿼리가 날라가면, 최적화 할 수 있는 여지자체가 없기 때문이다.
쓰기 지연 SQL 저장소에 쿼리들을 모아뒀다가 한꺼번에 DB로 날릴 수 있는 장점이 있다.
(최적화, 효율)
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction()
tx.begin(); // 트랜잭션 시작
// 영속된 객체 조회
Member memberA = em.find(Member.class, "memberA");
// 영속된 객체의 데이터 수정
memberA.setUsername("hello");
memberA.setAge(20);
// 데이터 수정 후, 다시 저장해야하지 않을까?
// em.persist(memberA);
// 트랜잭션 커밋, 커밋하는 순간 DB에 UPDATE 쿼리를 날린다.
tx.commit();
스냅샷
에 저장해둔다.영속성 컨텍스트의 변경내용을 DB에 반영하는 것이다.
트랜잭션 커밋 시, 자동으로 플러시가 발생한다.
플러시 이후에 영속성 컨텍스트가 비워지는 것이 아니다.
영속성 컨텍스트는 그대로 유지된다.
commit 직전에만 DB와 동기화하면 된다.
쓰기 지연 SQL 저장소
에 등록쓰기 지연 SQL 저장소
의 쿼리를 DB에 전송플러시를 직접 호출한다.
Member member = new Member(1L, "member1");
em.persist(member);
em.flush();
System.out.println("================");
tx.commit();
플러시 자동 호출
플러시 자동 호출