객체 지향 프로그래밍 vs relational DB
패러다임 불일치
상속
연관관계
데이터 타입
데이터 식별 방법
객체랑 RDB랑 어떻게 매핑을 해서 쓸 것인가?
"Entity를 영구 저장하는 환경."
내부 구현이 어떻게 되는가?
application과 database사이의 중간 매개체

하지만 EntityManger 도 자신의 인스턴스를 관리해줄 곳이 필요한데 그런 공간을 만들어 주는 곳이 EntityManagerFactory 이다. (Factory같은 경우는 한번 생성하는데 비용이 많이 들기 때문에 한번 생성 후 애플리케이션 전체에 공유)
EntityMangerFactory 생성 시 커넥션 풀도 만들어 준다

EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//EntityManager는 데이터 변경시 transaction을 시작해야 한다
transaction.begin(); //transaction시작
em.persist(memberA); //쓰기지연 SQ저장소에 INSERT 저장하고 1차 캐시에 memberA를 저장함.
em.persist(memberB); //쓰기지연 SQ저장소에 INSERT 저장하고 1차 캐시에 memberA를 저장함.
//여기까지 INSERT SQL을 DB에 보내지 않음
transaction.commit(); //커밋하는 순간 flush()호출 : DB에 SQL저장소에 있던 쿼리를 보냄

⟹ 수정 후 다시 em.persist(member)할 필요가 없다
쓰기 지연 SQL 저장소 : JPA는 transaction이 commit되는 시점에 변경을 반영함.
Member member1 = em.find(Member.class, 1L); // 조회
member1.setName("ha");
em.persist(member1) // ???
transaction.commit();
1차 캐시 내부 공간에서 만약 사용자가 em.persist를 하면 snapshot으로 해당 객체를 저장
member.setName('ha') 와 같은 코드로 setter를 호출해서 데이터를 바꿀 때 기존에 있던 스냅 샷과 바꾼 Member 객체 간 데이터를 비교해서 다르다면 Update 쿼리문을 자동으로 날려준다
Member memberA = em.find(member.class, "memberA");
em.remove(memberA); //entity삭제
Member a = em.find(Member.class, "memberA");
member b = em.find(Member.class, "memberB");
a == b ?? // true
flush 자동 호출 : i) transaction이 commit될 때 ii) JPQL 쿼리 실행할때 자동으로
or em.flush() (직접 호출하는 방법, 자동으로 ㄴㄴ)
ㄱ. dirty checking 변경 감지
ㄴ. 수정된 entity를 쓰기 지연 SQL 저장소에 등록
ㄷ. 쓰기 지연 SQL저장소의 쿼리를 DB에 전송