Entity를 영구 저장 하는 환경
어플리케이션(일단 '자바 코드 그 자체'라고 간주하기)이 DB에서 꺼내온 데이터 객체를 보관
EntityManager 를 통해 Entity를 저장/조회할 때, 영속성 컨텍스트에 접근/관리 가능
EntityManager 를 생성할 때, 하나 만들어짐
EntityManage 마다 개별적으로 부여되는, 어떠한 논리적 공간
JPA를 이해하는데 가장 중요한 용어
// 엔티티(minsook)를 생성
Member minsook = new Member();
member.setId("minsook");
member.setUsername("민숙");
// 엔티티 매니저를 통해 영속성 컨텍스트에 해당 엔티티(minsook)를 저장
// entityManager.persist(minsook); 으로 해도 동일함
em.persist(minsook);
// 엔티티를 영속성 컨텍스트에서 분리해, 준영속 상태로 만든다.
em.detach(minsook);
// 영속성 콘텍스트를 비워도, 관리되던 엔티티는 준영속 상태가 된다.
em.clear();
// 영속성 콘텍스트를 종료해도, 관리되던 엔티티는 준영속 상태가 된다.
em.close();
em.remove(minsook)
// 1차 캐시에서 조회하는 방법
// Map의 형태로 만들어짐 → (value에는 해당 entity값, key에는 id값)
// em.find(엔티티 클래스 타입, 식별자 값);
Member member = em.find(Member.class, "member1");
영속성 컨텍스트 내부에 있는 캐시를 '1차 캐시'라고 하며,
영속 상태의 엔티티를 1차 캐시에 저장
데이터는 1차 캐시가 아닌 다른 곳에 있는 경우가 多
→ 그래서, DB를 이용하는 작업은 상대적으로 부하와 비용이 심하다.
부하가 심한 작업을 자주하는 것을 줄이기 위해, 영속성 컨텍스트 내부에 1차캐시를 둔다.
(= 데이터를 조회할 때마다, DB로 SQL쿼리(“SELECT * FROM….”과 같은)를 내는 일은 막아야 한다는 것)
1차 캐시에 데이터가 저장되면, memberB를 find 하는 요청이 다시 들어와도, 굳이 DB로 다녀올 필요 X
→ 즉, 전에 불러온 것을 다시 빠르게 사용 할 수 있도록 그걸 담아두는 공간이 '영속성 컨텍스트'
entityManager.flush();
em.find(member)를 사용해 member를 저장해도, 바로 INSERT SQL이 DB에 보내지는 것이 X
→ EntityManager 는 트랜잭션을 커밋하기 직전까지 내부 쿼리 저장소에 INSERT SQL을 모아두고,
트랜잭션을 commit 할 때 모아둔 쿼리를 DB에 보낸다.
MemberA, MemberB를 생성할 때마다 DB 를 다녀오지 않도록,
효율성을 위해 내부에 “쓰기 지연 SQL 저장소”를 둔다.
flush
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Member member = em.find(Member.class, "member1");
member.setName("노영삼");
transaction.commit();
JPA 는 '1차 캐시'와 '쓰기 지연 SQL 저장소'를 이용해서, 데이터 변경을 감지해서 자동 수정
(DirtyChecking: 트랜잭션 안에서 엔티티의 변경 발생 시, 변경 내용을 자동으로 DB에 반영하는 JPA의 특징 ≒ 수정)
변경 감지 : 영속성 컨텍스트가 관리하는 영속 상태의 엔티티만 적용
데이터의 어플리케이션 단의 동일성을 보장
영속 엔티티의 동일성 보장
Member member1 = em.find(Member.class, "minsook");
Member member2 = em.find(Member.class, "minsook");
System.out.println(member1 == member2) // true
동일성 비교 : 실제 인스턴스 & 인스턴스가 가지고 있는 값이 같다. == 을 사용해 비교
동등성 비교 : 실제 인스턴스는 다를 수 있지만, 인스턴스가 가지고 있는 값이 같다. equals() 메소드를 구현해서 비교
Entity의 영속 상태에는 식별자 값이 반드시 있어야 한다.
→ 영속성 컨텍스트가 Entity를 식별자 값으로 구분하기 때문
참고: JPA 영속성 컨텍스트란?
참고: JPA 더티 체킹(Dirty Checking)이란?
참고: [Spring JPA] 영속성 컨텍스트(Persistence Context)