application 로딩 때 DB마다 딱 1개 생성되어야 함
WAS가 종료되는 시점에 EntityManagerFacotry를 닫음 -> connection pooling에 대한 리소스가 relase
(entityManagerFactory.close();
)
thread 생성될 때마다(요청 올 때마다) Entity Manager 생성
DB connection pool을 통해 DB 접근
transaction 단위를 수행할 때마다 생성 => 요청마다 사용하고 닫음
thread간에 공유하면 안됨 => transaction이 끝나면 닫아줘야 됨 => DB Connection을 반환
entityManager.close();
데이터를 변경하는 CRUD 작업의 경우 transaction 안에서 이루어져야 함.
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
transaction.commit();
1차 캐시
- @Id
- Entity
- Snapshot (값을 읽어온 최초의 상태)
entity를 영구 저장하는 환경
Entity Manager가 생성되면 1:1로 영속성 컨텍스트가 생성
2차 캐시
여러 명이 사용하는 Application 전체에서 공유하는 캐시
em.persist(객체);
객체를 영속성 컨텍스트(1차 캐시)에 Map<Key, Value>로 저장 (DB 저장x)
Key : @Id로 선언한 필드값
value : 해당 Entity
em.persist(객체);
1차 캐시에서 객체 조회 -> 없으면 DB에서 조회한 뒤 1차 캐시에 저장
같은 1차 캐시 에서 조회하기 때문에, 같은 reference가 됨
em.find(클래스.class, "클래스ID값");
Member a = entityManager.find(Member.class, "a");
Member b = entityManager.find(Member.class, "a");
같은 1차 캐시(transaction)에서 조회하기 때문에, a와 b는 같은 reference를 참조하고있다. 따라서, a==b가 된다.
1차 캐시로 반복 가능한 읽기(repetable read)등급의 트랜잭션 격리수준은 db(entity manager)가 아닌 애플리케이션(entity manager factory) 차원에서 제공한다.
객체를 영속성 컨텍스트에서 삭제
em.remove(객체);
EntityTransaction transcation = em.getTransaction();
transaction.begin();
em.persist(객체); // 객체를 영속성 컨텍스트에 저장
transaction.commit(); // commit하기 전 flush를 호출해 쓰기지연 저장소에 쌓아놨던 curd sql을 보낸다.
transaction.commit()
시 flush()
가 먼저 작동
entity와 snapshot을 일일이 비교 -> 변경사항 있으면 update 쿼리를 만들어 쓰기 지연 SQL 저장소에 넣는다.
@DynamicUpdate
dirty checking의 update 쿼리는 모든 필드를 대상으로 함.
엔티티 수정 시 변경된 필드만 반영되게 할 수 있음@Entity @DynamicUpdate public class EntityClass...
영속성 컨텍스트의 변경 내용을 DB에 반영.
transaction commit 전에 flush 동작 -> 쓰기지연 저장소에 쌓아놨던 insert, update, delete sql들이 날라감.
flush를 사용한다고 1차 캐시, 즉 영속성 컨텍스트가 비워지는것이 아님!!!
변경을 감지한다. (Dirty Checking)
수정된 Entity를 쓰기 지연 SQL 저장소에 등록한다.
쓰기 지연 SQL 저장소의 Query를 DB에 전송한다. (등록, 수정, 삭제 Query)