Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags more
Archives
Today
Total
관리 메뉴

요리사에서 IT개발자로

스파르타 부트캠프 Spring Master 2강 영속성 컨텍스트 기능 본문

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)라 한다.
반응형