JAVA, Spring 공부중
엔티티 매니저 팩토리
엔티티 매니저
JPA 가장 중요한 2가지
객체와 RDB 매핑하기
엔티티를 영구 저장하는 환경
EntityjManager.persist(entity); 를 사용하면 entity객체를 DB에 저장하는게 아니라 영속성 컨텍스트를 통해서 entity를 영속한다는 뜻임. entity를 영속 컨텍스트에 저장한다는 것.
Member member = new Member();
member.setId("member1");
member.set Name("memberName");
// 객체를 생성한 상태(비영속)
Member member = new Member();
member.setId("member1");
member.setName("memberName");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// 객체를 저장한 상태(영속) - 이 때 DB에 저장되는 것은 아님.
// 트랜잭션 커밋을 할 때 DB로 날라가는거임.
em.persist(member);
1) em.persist() 할 때
2) find로 해서 DB에서 찾아 영속 컨텍스트 내에 캐시가 생성되어 JPA가 관리하는 상태
// 회원 엔티티를 영속성 컨텍스트에서 분리한 상태 (준영속 상태)
em.detach(entity) : 특정 엔티티만 준영속 상태로 전환
em.clear() : 영속성 컨텍스트 완전히 초기화
em.close() : 영속성 컨텍스트 종료
// 영속성 컨텍스트에서 객체를 삭제한 상태(삭제)
em.remove(member);
영속 컨텍스트 안에 1차 캐시가 있어 (기본키, 객체)의 형태로 일시 저장이 된다. 맨 처음 DB에서 조회 후 그 다음부터는 1차 캐시에 있는 내용을 조회한다.
엔티티 매니저는 데이터 트랜잭션 단위로 만들고, 트랜잭션이 끝날 때 같이 종료를 시키기 때문에 큰 이점은 되지 않는다. 한 개의 요청이 있고, 요청이 끝나면 영속 컨텍스트를 지우기때문에 캐시의 효과는 미비함. 한 트랜잭션 안에서만 효과가 있음.

System.out.println(a == b); //동일성 비교 true. 같은걸로 취급됨.
1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공.


Entity em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(memberA);
em.persist(memberB);
//여기까지 insert sql을 DB로 보내지 않음. 쿼리가 영속 컨텍스트 안에 있는 쓰기 지연 SQL 저장소에 보관이 되었다가 나감.
//커밋하는 순간 DB에 insert sql을 보냄.
transaction.commit();
// 이 옵션을 persistence.xml에 넣으면 사이즈 만큼 모아서 DB에 한번에 넣기가 가능.
<property name="hibernate.jdbc.batch_size" value="10"/>
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");
// 영속 엔티티 데이터 수정
memberA.setUsername("hi");
memberA.setAge(10);
//em.update(member) 이런 코드는 필요하지 않다. 이유는 영속 컨텍스트 안에서 스냅샷과 비교 후 변경을 감지하여 update문을 자동 생성하기 때문.
transaction.commit();

1) 커밋을 하면 내부적으로 flush() 실행 후
2) 엔티티와 스냅샷을 비교함. 1차 캐시 내에는 1차 캐시와 스냅샷(영속 컨텍스트에 들어온 당시의 값을 저장해둠)이 있음. 값을 변경하게 되면 flush()가 실행이 되고 변경된 내용과 스냅샷을 비교함.
3) 바뀐 내용을 확인하면(변경 감지) 쓰기 지연 SQL 저장소에 update문을 생성해 넣어둠.
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//중간에 JPQL 실행
query = em.createQuery("select m from Member m", Member.class);
List<Member> members = qeury.getResultList();
위의 코드에서 em.persist(memberA);~em.persist(memberA);를 실행하고 em.createQuery를 실행하면 아직 DB에 member들을 저장을 안해서 불러올 수가 없음. 문제가 생길 것을 방지하고자 JPQL은 쿼리 날리면 무조건 flush()를 날려버림. 그래서 A~C가 조회될 수 있음.
em.setFlushMode(FlushModeType.COMMIT)