JPA에서 객체와 관계형 데이터베이스의 매핑 뿐 아니라 가장 중요한 요소 중 하나
엔티티를 영구 저장하는 환경
사용 방법
사용 환경
엔티티의 생명주기
비영속
영속성 컨텍스트와 관련 없는 상태
Book book=new Book();
위의 코드 처럼 아무런 처리과정 없이 자바에서 객체만 생성한 형태를 비영속이라 함
영속
영속성 컨텍스트에 관리되는 상태
//객체 생성(비영속)
Book book=new Book();
// Entitty Manager Factory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
//EntityManager 생성
EntityManager em = emf.createEntityManager();
//Transaction 생성
EntityTransaction tx = em.getTransaction();
tx.begin();
//객체를 저장(영속)
em.persist(book);
위의 코드 처럼 생성된 객체를 EntityManager에 저장한 상태를 영속상태라고 함
준영속
영속성 컨텍스트에 저장되었다가 분리된 상태
영속성 컨텍스트가 제공하는 기능 사용 못함
em.detach(book);
//영속성 컨텍스트를 완전히 초기롸
em.clear();
//영속성 컨텍스트를 종료
em.close();
삭제
영속성 컨텍스트에서 삭제된 상태
em.remove(book);
//객체 생성(비영속)
Book book=new Book();
book.setId("1");
// Entitty Manager Factory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
//EntityManager 생성
EntityManager em = emf.createEntityManager();
//Transaction 생성
EntityTransaction tx = em.getTransaction();
tx.begin();
//객체를 저장(영속) , 1차 캐시에 저장
em.persist(book);
// 1차 캐시에서 조회
Book findBook=em.find(Book.class,"1");
// DB에서 조회
Book findBook=em.find(Book.class,"2");
위의 코드 처럼 객체의 아이디가 "1"로 정해진 객체는 현재 Transaction이 Commit 되지 않은 시점에서 Persist되었기 때문에 아직 1차 캐시에 있음. 아이디가 "2"로 정해진 객체는 1차 캐시에 없기 때문에 DB에서 조회하게 됨.
//DB에서 조회
Book a=em.find(Book.class,"1");
//1차 캐시에서 조회
Book b=em.find(Book.class,"1");
a==b; //True
영속성 컨텍스트는 1차 캐시를 이용한다고 하였습니다. 위의 코드에서 a의 경우 일단 영속성 컨텍스트의 1차 캐시에 존재하지 않으므로 DB에서 조회되며 조회된 객체는 1차 캐시에 저장됩니다. b의 경우는 1차 캐시에 아이디 "1"을 가진 객체가 존재하므로 1차 캐시에서 조회하게 됩니다. 따라서 a와 b는 동일한 객체를 조회하도록 됩니다!
//객체 생성(비영속)
Book book1=new Book();
book.setId("1");
Book book2=new Book();
book.setId("2");
// Entitty Manager Factory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
//EntityManager 생성
EntityManager em = emf.createEntityManager();
//Transaction 생성
EntityTransaction tx = em.getTransaction();
tx.begin();
//객체를 저장(영속) , 1차 캐시에 저장
em.persist(book1);
em.persist(book2);
//아직 DB에 Insert 문을 보내지 않음
tx.commit();
//커밋하는 순간 Insert문을 한번에 보냄
위의 코드는 그 예를 보여 주고 있습니다!
// Entitty Manager Factory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
//EntityManager 생성
EntityManager em = emf.createEntityManager();
//Transaction 생성
EntityTransaction tx = em.getTransaction();
tx.begin();
//객체를 조회
Book book=em.find(Book.class,"1);
book.setName("Nice");
//조회된 엔티티 수정??? 또 다른 처리 과정이 필요하지 않을까!
tx.commit();
//커밋하는 순간 Insert문을 한번에 보냄
위의 코드는 영속성 컨텍스트에 조회된 객체에서 객체의 데이터를 수정하고 있습니다. 여기서 의문이 들죠.. '객체가 변경되었으니 영속을 또 시켜야하나?? 아니면 update라는 code를 새로 만들어야 하나??' 그럴 필요 없이 Entity Manager는 객체의 스냅샷을 남겨 Trasaction이 commit하기 전에 스냅샷과 객체를 비교하게 되어 변경된 부분이 있으면 commit 시점에 update문을 날리게 됩니다.
Flush
영속성 컨텍스트의 변경내용을 DB에 반영
- 발생 시점
- em.flush() 직접 호출
- Transaction Commit시 자동 호출
- JPQL 쿼리 실행시 자동 호출
- 플러시 모드 옵션
em.setFlushMode(FlushModeType.COMMIT)
- FlushModeType.AUTO : default
- FlushModeType.COMMIT : Commit할때만 Flush
이 글은 인프런 김영한님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편'을 수강하고 작성합니다.
출처:https://www.inflearn.com/course/ORM-JPA-Basic