RDB의 Table과 매핑되는 객체입니다.
@Entity
@Getter
@Setter
@Table(name = "customers")
public class Customer {
@Id
private long id;
private String firstName;
private String lastName;
}

이미지출처-프로그래머스 강의
엔티티 매니저 팩토리는 각 요청에 대해 엔티티 매니저를 생성합니다.
엔티티 매니저는 DB 커넥션 풀을 관리하는 객체로부터 커넥션을 가져와 DB와 연산작업을 합니다.
엔티티 매니저는 트랜잭션을 시작할 때, 커넥션을 획득합니다.(DB에 실제로 커밋이 발생할때 커넥션을 가져와 사용합니다.)
JPA를 이용하는데 가장 중요한 요소입니다.
이미지출처-프로그래머스 강의
엔티티는 엔티티 매니저에 의해 영속성 컨텍스트에서 관리됩니다.
persist메소드 : 영속화 하겠다는 의미입니다. 즉 엔티티 객체를 영속성 컨텍스트 안에서 관리를 한다는 의미입니다.
JPA는 트랜잭션을 커밋하는 순간 영속성 컨텍스트에 새로 저장된 엔티티를 DB에 반영합니다. (FLUSH)플러시(flush)는 영속성 컨텍스트의 변경 내용을 DB에 동기화하는 작업인데, 이때 등록, 수정, 삭제한 엔티티를 DB에 반영한다.
이미지출처-프로그래머스 강의
// 객체가 영속성컨텍스트, 데이트베이스와 무관한 상태입니다.
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
// customer객체가 영속성 컨텍스트에서 관리됩니다.
// em == EntityManager
em.persist(customer);
// 영속상태의 customer객체 (엔티티)를 영속성컨텍스트에서 분리합니다.
em.detach(Customer);
// 영속상태의 모든 객체를 영속성컨텍스트에서 분리합니다.
em.clear()
// 영속성컨텍스트를 종료합니다.
em.close()
// customer 엔티티를 영속성컨텍스트에서 분리하고, DB에서도 삭제합니다.
em.remove(customer)
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("honggu");
customer.setLastName("kang");
em.persist(customer); // 4-2) 영속화
transaction.commit(); // 5) 트랜잭션 commit
//트랜잭션이 커밋이 되는 순간 쿼리가 수행됩니다. (flush연산으로 DB와 동기화가 됩니다.)

이미치출처-프로그매러스 강의
@Test
void 조회_1차캐시_이용() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction() ;
transaction.begin();
Customer customer = new Customer();
customer.setId (1L);
customer.setFirstName("aaa");
customer.setLastName("bbb");
em.persist(customer);
transaction.commit;
Customer entity = em.find(Customer.class, 1L); // 1차 캐시에서 조회합니다.
log.info("{} {}", entity.getFirstName(), entity.getLastName());
}

이미지 출처-프로그래머스 강의
DB에 질의하지 않고 1차 캐시에서 결과를 반환합니다.
@Test
void 조회() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction() ;
transaction.begin();
Customer customer = new Customer();
customer.setId (2L);
customer.setFirstName("ccc");
customer.setLastName("ddd");
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); // 1차 캐시를 사용하므로 SELECT 쿼리가 수행되지 않습니다.
}

이미치출처-프로그매러스 강의
DB에 질의하여 1차 캐시에 저장한 후에 결과를 반환합니다.
@Test
void 수정() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction() ;
transaction.begin();
Customer customer = new Customer();
customer.setId (1L);
customer.setFirstName("aaa");
customer.setLastName("bbb");
em.persist(customer);
transaction.commit;
// 엔티티를 영속화 한 후, 커밋을 해서 flush()를 통해 DB에 저장합니다.
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
entitiy.setFirstName("ccc");
entitiy.setLastName("ddd");
// em.update(entity)를 할 필요가 없습니다.
transaction.commit(); // 여기서 flush()를 통해 UPDATE 쿼리가 수행됩니다.
}

이미지 출처-프로그래머스 강의
[변경감지 - dirty checking]
JPA 는 엔티티를 영속성 컨텍스트에 보관할 때, 최초 상태를 복사해서 저장해 두는데 이것을 스냅샷이라 합니다. 그리고 플러시 시점에 스냅샷과 엔티티를 비교해서 변경된 엔티티를 찾습니다. 만일 스냅샷과 비교하여 변경된 내용이 있을 경우 update Query를 수행합니다. (변경 감지는 영속성 컨텍스트가 관리하는 영속 상태의 엔티티에만 적용됩니다.)
@Test
void 삭제() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction() ;
transaction.begin();
Customer customer = new Customer();
customer.setId (1L);
customer.setFirstName("aaa");
customer.setLastName("bbb");
em.persist(customer);
transaction.commit;
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
em.remove(enmtity); // flush()를 통해 DELETE 쿼리가 수행됩니다.
}