영속성 컨텍스트란?
영속성 컨텍스트란 "엔티티를 영구적으로 저장하는 환경"을 의미하며 눈에 보이지 않는 논리적인 개념이다.
엔티티 매니저를 통해 영속성 컨텍스트에 접근이 가능하다.
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
...
}
}
엔티티의 생명주기
- 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
// 객체를 생성한 상태(비영속) Member member = new Member(); member.setId("member1"); member.setUsername("회원1");
- 영속 (managed) : 영속성 컨텍스트에 관리되는 상태
// 객체를 생성한 상태 Member member = new Member(); member.setId("member1"); member.setUsername("회원1"); em.persist(member);
- 준영속 (detached) : 영속성 컨텍스트에 저장 되었다가 분리된 상태이며 영속성 컨텍스트의 제공기능을 사용 못한다.
em.detach(member); // 특정 엔티티만 준영속 상태로 전환 em.clear(); // 영속성 컨텍스트를 완전히 초기화 em.close(); // 영속성 컨텍스트를 종료
- 삭제(removed) : 엔티티를 삭제하여 엔티티매니져에 값이 없는 상태
//삭제 대상 엔티티 조회 Member memberA = em.find(Member.class, "memberA"); // 객체를 삭제한 상태(삭제) em.remove(member);
영속성 컨텍스트의 장점
- 1차 캐시
Member member = new Member();member.setId("member1"); member.setUsername("회원1"); em.persist(member); // 1차 캐시에 저장됨 Member findMember1 = em.find(Member.class, "member1"); // 1차 캐시에서 조회(디비커넥션X) Member findMember2 = em.find(Member.class, "member2"); // 데이터베이스에서 조회
- 동일성(identity) 보장 : 영속 엔티티의 동일성 보장
Member a = em.find(Member.class, "member1"); Member b = em.find(Member.class, "member1"); System.out.println(a == b) // 동일성 비교 true
- 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); //엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다. tx.begin(); // [트랜잭션] 시작 em.persist(memberA); em.persist(memberB); //여기까지 INSERT SQL을 데이터베이스에 보내지 않는다. //커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다. tx.commit(); // [트랜잭션] 커밋
- 변경 감지(Dirty Checking) : 영속 엔티티의 데이터 수정이 확인되면 데이터베이스 업데이트
EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); // [트랜잭션] 시작 // 영속 엔티티 조회 Member memberA = em.find(Member.class, "memberA"); // 영속 엔티티 데이터 수정 memberA.setUsername("hi"); memberA.setAge(10); transaction.commit(); // [트랜잭션] 커밋
플러시( flush)
- 영속성 컨텍스트를 비우지는 않는다.
- 영속성 컨텍스트의 변경내용을 데이터베이스에 동기화한다.
- 트랜잭션이라는 작업 단위가 가장 중요하다. (커밋 직전에만 동기화 하면 된다.)
플러시 발생
- 변경 감지
- 수정된 엔티티 쓰기 지연 SQL 저장소에 등록한다.
- 쓰기 지연 SQL 저장소의 쿼리를 데이터베이스에 전송한다.
영속성 컨텍스트를 플러시하는 방법
- em.flush() 를 직접 호출한다.
- 트랜잭션 커밋하여 플러시를 자동 호출한다.
- JPQL 쿼리를 실행하여 플러시를 자동 호출한다.
// JPQL 쿼리 실행 시 플러시가 자동으로 호출되는 이유 em.persist(memberA); em.persist(memberB); em.persist(memberC); // 중간에 JPQL 실행 // JPQL이 실행되기 전 memberA ~ C 의 값이 저장되어야 정상적인 목록을 불러올 수 있기 때문이다. query = em.createQuery("select m from Member m", Member.class); List<Member> members = query.getResultList();
플러시 모드 옵션
- em.setFlusMode(FlusModeType.COMMIT)
- FlushModeType.AUTO : 커밋이나 실행할 때 플러시 (기본값)
- FlushModeType.COMMIT : 커밋할 때만 플러시
'BackEnd > JPA' 카테고리의 다른 글
[JPA] 프록시와 연관관계 관리 (0) | 2024.02.27 |
---|---|
[JPA] 상속관계 매핑 전략(@Inheritance, @DiscriminatorColumn) (0) | 2024.02.23 |
[JPA] 연관관계 매핑 (0) | 2024.02.21 |
[JPA] 연관관계 매핑 기초 (0) | 2024.02.20 |
[JPA] 엔티티 매핑 (0) | 2024.02.13 |