영속성 컨텍스트
- 엔티티를 영구 저장하는 환경
- EntityManger.persist(entity);
- 논리적인 개념으로 눈에 보이지 않음
- 엔티티 매니저를 통해서 영속성 컨텍스트에 접근
- 내부에 1차 캐시, 쓰기 지연 SQL 존재
엔티티 생명주기
- 비영속
- 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
- 영속
- 영속성 컨텍스트에 관리되는 상태로 영속성 컨텍스트 안에 객체가 들어간다고 생각
- em.persist 이후 바로 데이터베이스 쿼리가 나가는 것이 아닌, commit 순간에 영속성 컨텍스트 안의 객체가 데이터베이스로 날아감
- 준영속
- 영속성 컨텍스트에서 분리된 상태(detached)
- 영속성 컨텍스트가 제공하는 기능을 사용 못함(commit 등)
- em.detach(entity) : 해당 entity를 준영속 상태로 만듬
- em.clear() : 영속성 컨텍스트 자체를 초기화
- em.close() : 영속성 컨텍스트 종료
- 삭제
- 삭제된 상태
// 객체를 생성한 상태(비영속)
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차 캐시에 저장)
// 1차 캐시에 저장
em.persist(member);
// 1차 캐시에 있으면 db를 거치지 않고 바로 조회, SELECT 쿼리 로그 없음
em.find(Member.class, "member1");
// 1차 캐시에 없으면 db에서 조회, SELECT 쿼리 로그 있음
// 조회 후 다시 1차 캐시에 저장 후 반환
em.find(Member.class, "member2");
// 이후 member2 조회 시 1차 캐시에서 조회, SELECT 쿼리 로그 없음
2. 동일성 보장
Member findMember1 = em.find(Member.class, 101L);
Member findMember2 = em.find(Member.class, 101L);
System.out.println("result = " + (findMember1 == findMember2)); // true
3. 트랜잭션을 지원하는 쓰기 지연
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
// 엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 함
tx.begin(); // 트랜잭션 시작
em.persist(memberA);
em.persist(memberB);
// 여기까지 INSERT SQL을 DB에 보내지 않음
// 로그에서 INSERT SQL 안나옴
// 커밋하는 순간 DB에 INSERT SQL을 보냄
tx.commit(); // 트랜잭션 커밋
- persist 시 쓰기 지연 SQL 저장소에 저장
- commit 순간에 지연 SQL 저장소에 쌓인것들 모두 저장
- persistence.xml에서 배치 사이즈 조절을 통해 원하는 개수의 SQL 설정 가능
4. 변경 감지(Dirty checking)
Member findMember = em.find(Member.class, 150L);
findMember.setName("B"); // A -> B 로 변경됨, 이 순간 update 쿼리는 날아감
// em.persist(findMember); // 불필요
...
tx.commit();
- update 시 em.persist 호출 불필요
- 쉽게 생각해서 자바 컬렉션에서 인덱스를 통한 데이터에 접근하여, 데이터 수정 후 다시 저장하지 않는 것과 비슷
플러시
- 흔히 '영속성 컨텍스트를 플러시 한다' 라고 표현
- 영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 것(동기화)
- 플러시 발생은 commit 실행 시 자동으로 발생하나 직접 호출 또한 가능
- 자동
- 변경 감지 시
- 수정된 엔티티 쓰기 지연 SQL 저장소에 등록 시
- 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스 전송 시
- 직접 호출
- em.flush()
- commit 실행
- JPQL 쿼리 실행 (em.createQuery("select m from Member m", Member.class);)
- 자동
- 영속성 컨텍스트를 비우지 않음
- 1차 캐시와는 무관(1차 캐시의 내용이 지워지지 않음)
- 트랜잭션 작업 단위가 중요 -> commit 직전에만 동기화 하면 됨
'Spring > JPA' 카테고리의 다른 글
MappedSuperclass (0) | 2023.12.20 |
---|---|
상속관계 매핑 (0) | 2023.12.20 |
연관관계 매핑 (1) | 2023.12.19 |
엔티티 매핑 (0) | 2023.08.25 |
JPA(Java Persistence API)란 (0) | 2023.08.17 |