Spring
스파르타 부트캠프 Spring Master 2강 영속성 컨텍스트 기능
H.S-Backend
2024. 5. 22. 23:23
영속성 컨텍스트는
Entity객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간
https://hs-backend.tistory.com/126
스파르타 부트캠프 Spring Master 2강 영속성 컨텍스트
영속성 컨텍스트란 지속성을 의미한다(persistence) Persisten를 객체의 관점으로 해석해보았을 경우객체가 생명(객체가 유지되는 시간)이나공간(객체의 위치)을 자유롭게 유지하고이동할 수 있는
hs-backend.tistory.com
영속성 컨텍스트는 내부적으로 캐시 저장소를 갖고있다.
캐시 저장소는 Map자료 구조형태로 되어있다.
Key => @Id로 매핑한 기본키(식별자)값을 저장
Value => 해당 Entity클래스의 객체를 저장
영속성 컨텍스트는 캐시 저장소의 Key에 저장한 식별자 값을 사용하여 Entity객체를 구분하고 관리한다.
em.persist(memo); 메서드 호출시 memo Entity객체를 캐시저장소에 저장한다.
Entity조회
캐시저장소에 조회하는 Id가 존재하지 않는 경우
em.find();로 먼저 조회하고
해당DB가 없다면 해당 값을 캐시 저장소에 저장하고 반환한다.
@Test
@DisplayName("Entity 조회 : 캐시 저장소에 해당하는 Id가 존재하지 않은 경우")
void test2() {
try {
Memo memo = em.find(Memo.class, 1);
System.out.println("memo.getId() = " + memo.getId());
System.out.println("memo.getUsername() = " + memo.getUsername());
System.out.println("memo.getContents() = " + memo.getContents());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
em.close();
}
emf.close();
}
캐시저장소에 조회하는 ID가 존재하는 경우
이미 존재하기 때문에 해당값을 반환한다.
@Test
@DisplayName("Entity 조회 : 캐시 저장소에 해당하는 Id가 존재하는 경우")
void test3() {
try {
Memo memo1 = em.find(Memo.class, 1);
System.out.println("memo1 조회 후 캐시 저장소에 저장\n");
Memo memo2 = em.find(Memo.class, 1);
System.out.println("memo2.getId() = " + memo2.getId());
System.out.println("memo2.getUsername() = " + memo2.getUsername());
System.out.println("memo2.getContents() = " + memo2.getContents());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
em.close();
}
emf.close();
}
1차 캐시를 사용함으로 장점은
DB조회 횟수를 줄이고
DB row 1개 당 객체 1개가 되는것을 보장한다(객체 동일성 보장)
@Test
@DisplayName("객체 동일성 보장")
void test4() {
EntityTransaction et = em.getTransaction();
et.begin();
try {
Memo memo3 = new Memo();
memo3.setId(2L);
memo3.setUsername("Robbert");
memo3.setContents("객체 동일성 보장");
em.persist(memo3);
Memo memo1 = em.find(Memo.class, 1);
Memo memo2 = em.find(Memo.class, 1);
Memo memo = em.find(Memo.class, 2);
System.out.println(memo1 == memo2);
System.out.println(memo1 == memo);
et.commit();
} catch (Exception ex) {
ex.printStackTrace();
et.rollback();
} finally {
em.close();
}
emf.close();
}
같은 값을 조회하는 memo1 , memo2는 true,
다른 값을 조회하는 memo1, memo는 false
Entity삭제
똑같이 em.find();를 사용하여 먼저 조회하고
em.remove();를 사용하여 삭제한다.
@Test
@DisplayName("Entity 삭제")
void test5() {
EntityTransaction et = em.getTransaction();
et.begin();
try {
Memo memo = em.find(Memo.class, 2);
em.remove(memo);
et.commit();
} catch (Exception ex) {
ex.printStackTrace();
et.rollback();
} finally {
em.close();
}
emf.close();
}
쓰기 지연 저장소(ActionQueue)
DB에서 쿼리를 받아서 영속성 컨테스트로
레지스트를 받아서 수정되는 값은
Action Queue(쓰기지연저장소)에서 SQL을 모아두고있다가
Commit하면 한번에 DB에 반영된다.
flush()란
commit하기전 flush()를 할 경우
commit 되기전에 바로 DB로 저장된다.
변경감지(Dirty Checking)
JPA는 영속성 컨텍스트에 Entity를 저장할 때 최초 상태로 저장한다.
트랜잭션이 commit 이 되고 em.flush()가 호출이되면 Entity의 현상태와 저장한 최초상태를 비교한다.
변경 내용이 있다면 UpdateSQL을 생성하여
쓰기 지연저장소에 저장하고
모든 쓰기지연 저장소의 SQL(변경내용) 을 DB에 요청하여 수정이되는지 검사 후
마지막으로 DB의 트랜잭션이 commit되면서 반영된다.
변경 하고 싶은 데이터가 있다면 먼저 데이터를 조회
해당 Entity객체의 데이터를 변경하면
자동으로 Update SQL이 생성되고 DB에 반영된다
이러한 과정을 변경감지(Dirty Checking)라 한다.
반응형