비영속 (new/transient)
-> 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
영속 (managed)
-> 영속성 컨텍스트에 관리되는 상태
준영속 (detached)
-> 영속성 컨텍스트에 저장되었다가 분리된 상태
삭제 (removed)
-> 삭제된 상태
1차 캐시
동일성(identity) 보장
트랜잭션을 지원하는 쓰기 지연 (Transactional write-behind)
변경 감지 (Drity Checking)
지연 로딩 (Lazy Loading)
//엔티티를 생성한 상태 (비영속)
Member member = new Member();
member.setId("member1");
member.setUsername("회원1");
//엔티티를 영속
//em = entity manager
em.persist(member);
fun practice1(){
//JPA 특성을 가지고 있다.
val emf = Persistence.createEntityManagerFactory("hello")
val em = emf.createEntityManager()
// 비영속 상태이다.
val member = Member()
member.id = 101L
member.title = "테스트맨"
// transaction
val transaction = em.transaction
transaction.begin()
println("BEFORE") // before 찍힘
// 영속화 한다 (persist)
// 저장할 때 사용한다.
em.persist(member) // insert 날라감
println("AFTER") // after 찍힘
transaction.commit()
em.close()
emf.close()
}
이 function을 실행시키면 BEFORE, AFTER이 차례로 print가된 뒤 persist된다.
왜?
println("BEFORE") -> 1차 캐시로 저장 -> println("AFTER") -> commit(DB로 전달)
되기 때문
여기서 중요한 것은 1차 캐시 이다.
JPA를 통해 DB에 보내기 전 메모리에 1차 캐시로 데이터를 저장하고,
그 상태에서 @Transaction 안에서 즉시 사용될 수 있다.
fun practice2(){
// EntityManager 생성
val emf = Persistence.createEntityManagerFactory("hello")
val em = emf.createEntityManager()
//객체를 생성한 상태(비영속)
val member = Member()
member.id = 101L
member.title = "회원"
val transaction = em.transaction
transaction.begin()
//1차 캐시에 저장됨
em.persist(member)
//3번 멤버 조회
val member1 = em.find(Member().javaClass, 101L)
println("조회 결과 : " + member1.title)
transaction.commit()
em.close()
emf.close()
}
practice2 function를 실행하면, DB에서 불러오는 것이 아니라
1차캐시 에서 불러올 수 있다는 것을 알 수 있다.
즉, JPA는 1차 캐시에서 먼저 데이터를 찾고 없으면 DB에서 조회한다.
fun practice3(){
// EntityManager 생성
val emf = Persistence.createEntityManagerFactory("hello")
val em = emf.createEntityManager()
val transaction = em.transaction
transaction.begin()
//100번 멤버 조회
val member1 = em.find(Member().javaClass, 100L)
//100번 멤버 조회
val member2 = em.find(Member().javaClass, 100L)
println("비교 결과 : " + (member1 === member2))
transaction.commit()
em.close()
emf.close()
}
이건 어떻게 처리될까?
member1과 member2를 따로 조회하는 것이 아니라,
한 번에 조회한 뒤 비교 결과를 출력한다.