: 쿼리를 사용하지 않고도 트랜잭션이 끝나는 시점에 Persistence Context안에 변화가 있는 모든 엔티티 객체를 DB에 자동으로 반영
EntityManager
에 의해 관리됨@Id
: Persistence Context안에서 Entity CRUD 등 Entity와 관련된 모든 일 처리
EntityManagerFactory
가 thread safe하게 생성EntityManager em = emf.createEntityManager(); // 1)엔티티 매니저 생성
EntityTransaction transaction = em.getTransaction(); // 2)트랜잭션 획득
transaction.begin(); // 3)트랙잰셕 begin
Customer customer = new Customer(); // 4-1)비영속
customer.setId(1L);
customer.setFirstName("ayoung");
customer.setLastName("kim");
em.persist(customer); // 4-2)영속화
transaction.commit(); // 5)트랜잭션 commit // EntityManager의 flush()가 실행됨
1차 캐시를 이용
@Test
void 조회_1차캐시_이용() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("ayoung");
customer.setLastName("kim");
em.persist(customer);
transaction.commit();
Customer entity = em.find(Customer.class, 1L); // 1차 캐시에서 조회한다.
log.info("{} {}", entity.getFirstName(), entity.getLastName());
}
DB를 이용
@Test
void 조회() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(2L);
customer.setFirstName("ayoung");
customer.setLastName("kim");
em.persist(customer);
transaction.commit();
em.clear(); //영속성 컨텍스트를 초기화 한다.
Customer entity = em.find(Customer.class, 2L); // DB 에서 조회한다. SELECT ...
log.info("{} {}", entity.getFirstName(), entity.getLastName());
em.find(Customer.class, 2L); // SELECT Query 수행되지 않는다. 1차캐시 사용
}
JPA 는 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해 두는데 이것을 스냅샷이라 한다. 그리고 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾는다. 만일 스냅샷과 비교하여 변경된 내용이 있을 경우 update Query를 수행한다. (변경 감지는 영속성 컨텍스트가 관리하는 영속 성태의 엔티티에만 적용이 된다.)
@Test
void 수정() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("ayoung");
customer.setLastName("kim");
em.persist(customer);
transaction.commit();
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
entity.setFirstName("asdad");
entity.setLastName("adddddd");
transaction.commit(); // flush -> UPDATE ...
}
@Test
void 삭제() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("ayoung");
customer.setLastName("kim");
em.persist(customer);
transaction.commit();
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
em.remove(entity);
transaction.commit(); // flush -> DELETE ..
}
Reference
프로그래머스 백엔드 데브코스