728x90
반응형
영속성 컨텍스트란?
- 영속성 컨텍스트에 대해 알아본다.
- 동작을 알아본다.
영속성 컨텍스트
- JPA 를 이해하는데 기본이 된다.
- 논리적인 개념이다.
- 엔티티를 영구저장하는 환경
- EntityManager.persist(entity)
- 엔티티 매니저를 통해 영속성 컨텍스트에 접근한다.
엔티티 매니저를 통해 어떻게 접근하고 관리가 될까?
엔티티 매니저 팩토리와 엔티티
- EntityManagerFactory 는 웹에서 하나로만 생성하여 사용한다.
- EntityManager는 사용자의 요청마다 생성해서 사용한다.
- EntityManager는 내부적으로 DB 커넥션을 사용해 DB와 연결한다.
엔티티의 생명주기
EntityManager가 엔티티를 관리 하는 부분에서 엔티티의 생명주기 또한 중요하다.
- 비영속(new/transient)
영속성 컨텍스트와 전혀 관계가 없는 새로운 상태 - 영속(managed)
영속성 컨테스트에 관리 되는 상태 - 준영속(detached)
영속성 컨텍스트에 저장되었다가 분리된 상태 - 삭제(remove)
삭제된 상태
비영속
- 비영속은 JPA 즉 EntityManager 가 관리하지 않는 상태이다.
- 새로운 객체를 만들었을때 보통 비영속이다.
//객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
영속
- 영속은 EntityManager 가 관리하는 상태이다.
- 객체를 em.persist(member); 영속성 컨텍스트에 넘겨주면 된다.
//객체를 생성한 상태(비영속)
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);
영속성 컨텍스트의 이점
영속성 컨텍스트는 다음과 같은 이점들이 있다.
- 1차캐시
- 동일성보장
- 트랜잭션을 지원하는 쓰기지연
- 변경감지
- 지연로딩
1차캐시
- DB에 저장하기 전 영속성된 객체들을 저장하고 있는 캐시이다.
- 코드로 보면 setUsername 까지는 1차캐시에는 아무런 데이터가 없다.
- 사용자가 persist 로 객체를 넘겨주면 그때 부터 1 차캐시에 id 와 객체의 데이터가 저장된다.
//엔티티를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
// 1차 캐시에 객체정보가 저장됨
//엔티티를 영속
em.persist(member);
조회시 동작구조
- 1차 캐시에 저장후 조회를 하는경우
- 찾기위한 쿼리문은 수행되지 않는다.
- 1차 캐시에서 먼저 찾고 없으면 DB 에서 조회 하기 때문이다. - persist 로 객체정보를 영속 컨텍스트에 저장
- 조회시 캐시에서 조회
캐시에서 조회
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//1차 캐시에 저장됨
em.persist(member);
//1차 캐시에서 조회
Member findMember = em.find(Member.class, "member1");
DB에서 조회
- 영속성 컨텍스트에 해당 id 를 가진 객체가 없다면 DB 에서 조회한다.
- 조회한 객체를 영속성 컨텍스트에 저장한다.
Member findMember2 = em.find(Member.class, "member2");
동일성 보장
- 동일한 트랜잭션 안에서 JPA 는 동일성을 보장해준다.
- 즉 다음과 같은 코드로 비교가 가능하다는 것이다.
Member findMember2 = em.find(Member.class, 101L);
Member findMember3 = em.find(Member.class, 101L);
if (findMember2 == findMember3) {
System.out.println("findMember2 == findMember3");
}
트랜잭션을 지원하는 쓰기지연
쉽게 설명하면 버퍼에 데이터를 가지고 있다가 한번에 DB에 저장하는 개념이라고 생각하면
쉬울것 같다.
- persist를 쓴다고 바로 DB에 저장되는 것이 아니다.
- 일단 영속성 컨텍스트에 객체 정보를 담아둔다. - EntityTeansaction 에서 commit 함수를 호출해 주면 그때 DB에 쿼리가 날라간다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋
Commit
- 커밋이 되면 flus가 호출되고 DB에 sql 문을 날린다.
- 실제 DB 에서 commit을 한다
- <property name="hibernate.jdbc.batch_size" value="10"/> 속성으로 얼마나 모았다가
DB에 저장할지 정할수 있다.
변경감지
- 영속성으로 객체가 관리 될때 멤버의 속성이 변경 되었다
- commit 되는 시점에 EntityManager 가 엔티티와 스냅샷을 비교한다.
- 스냅샷은 최초로 읽어온 시점의 상태를 저장하고 있다.
- 변경을 확인후 update 쿼리를 수행한다.
- 코드를 보면 따로 update를 하는 함수가 없다.
- 자동으로 업데이트가 되기 때문이다.
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
transaction.commit(); // [트랜잭션] 커밋
참고: https://www.inflearn.com/course/ORM-JPA-Basic/lecture/21687?speed=1&tab=curriculum
728x90
반응형
'DataBase > JPA' 카테고리의 다른 글
[JPA] 준영속성 (0) | 2021.07.30 |
---|---|
[JPA] 플러시 (0) | 2021.07.30 |
[JPA] JPA CRUD 기본 (0) | 2021.07.30 |
[JPA] JPA 환경설정 (0) | 2021.07.29 |
[JPA] JPA 란? (0) | 2021.07.28 |
댓글