본문 바로가기
Framework & Lib/스프링

jpa 영속성 컨텍스트 개념

by 코딩공장공장장 2022. 6. 12.

영속성 컨텍스트

영속성 컨텍스트란 jpa에서 엔티티를 db에 반영하기 전에 영속화하는 공간이다. 

서버단에 존재하는 가상의 DB역할을 하는 일종의 메모리 공간이며 엔티티의 변화를 감지하여

DB에 반영전 우선적으로 작업하는 공간이라고 생각하면 된다.

 

영속성 컨텍스트의 구조를 보면 위와 같이 영속성 컨텍스트는 EntityManger 안에 존재하며

"1차 캐시 공간""SQL 저장소"로 이루어져 있다.

1차 캐시 안에서 사용자가 조회 및 수정한 엔티티가 관리되고

SQL저장소는 사용자 SQL을 저장하여 트랜잭션을 커밋하는 시점에 일괄적으로 DB에 반영한다.

 

1차 캐시 공간에서 엔티티를 관리하니 내가 사용하려는 엔티티와 동일한 엔티티가 캐시공간에 있다면

DB에 접근하지 않고 영속성 컨텍스트에 있는 엔티티를 사용할 수 있는것이다. 

 

여기에서 의문이 들 수 있을만한 내용이 엔티티의 동일 여부를 어떻게 판단하는지,

캐시공간이 전역적으로 사용되는 것인지, 캐시의 지속기간이 어느정도인지 궁금할 수 있을 것이다.

 

정답부터 말을 하면 엔티티의 동일여부는 오직 식별자(객체의 id, 테이블에서 pk)로 판단하고,

캐시공간은 전역적이지 않고 트랜잭션 단위이며 마찬가지로 캐시의 지속기간도 트랜잭션 단위이다.

따라서 영속성 컨텍스트는 논리적으로는 영구적이지만 실제로는 트랜잭션 단위의 휘발성 메모리 공간이다.

 

트랜잭션이 시작되면 EntityFactory가 쓰레드에 EntityManager를 할당한다.

만약 사용자가 엔티티 쓰기 작업을 하려 한다면

내부적으로 해당 엔티티의 식별자값을 가져와 select를 먼저 수행후 select를 통해 얻은 엔티티와 

사용자가 가져온 엔티티를 비교하여 변화된 필드를 감지한다. 

엔티티의 변화를 감지하는 과정을 "더티 체킹"이라고 한다. 

쓰기 작업 전 select를 통해 얻은 엔티티에 대한 스냅샷을 생성하여 사용자가 가져온 엔티티와 

 

더티체킹하여 변화가 일어났다면 update  쿼리를 만들어 바로 DB로 접근하지 않고 SQL 저장소에 쿼리를 저장한다.

이렇게 쿼리가 바로 실행되지 않고 SQL 저장소에 저장해두고

트랜잭션이 끝나면 한번에 실행되는 과정을 "쓰기 지연"이라고 한다.

 

쓰기 지연을 사용하게 되면 좋은점이 서버와 DB가 쿼리를 실행할 때 마다 접근하지 않고

한번에 처리하기 때문에 성능과 속도면에서 큰 효율을 얻을 수 있다.

 

다만 상황에 따라 쓰기 지연이 발생할 수 도 있고 발생하지 않을 수도 있다. 

이 부분은 굉장히 많은 상황에서 다르게 작동하여 다른 포스팅에서 테스트 결과와 함께 통해 공유 하겠다.

 

이렇게 해서 모든 작업이 끝나고 트랜잭션이 커밋되면 최종적으로 영속성 컨텍스트의 SQL 저장소에 있는 쿼리가

DB에 반영이 되고 영속성 컨텍스트는 트랜잭션 종료와 함께 파기 된다. 

 

 

 

++++++++++++ 참고사항 ++++++++++++

"JPA에 right outer join은 존재하지 않는다."

 

jpa는 mybatis와 다르게 데이터베이스 중심이 아닌 객체중심이기 때문에 right outer join의 개념은 없습니다.

 

어찌보면 당연한 말이지만 mybatis를 사용하는 저에게는 의구심이 드는 부분이었는데

 

엔티티는 오직 식별자로 구분하기 때문에 내가 가져오려는 엔티티의 식별자가 없는데 가져온다는 것은

 

객체중심 프로그래밍에서 존재하지 않는 것 같습니다.

 

데이터베이스 중심에서는 null이어도 다른 칼럼이 조회조건이 될 수 있어 가져올 수 있는데

 

엔티티의 경우에는 오직 식별자로 엔티티를 구분하니 조회하는 객체의 식별자가 없으면

 

조회불가, 즉 null이 허용되지 않습니다.

반응형