2 분 소요

Entity란?

  • DB에서 테이블과 매칭되는 개념이다
  • 하지만 무조건 테이블 A와 엔티티 A1의 값들이 1대1 매칭이 되는건 아니다.
  • 예로 컬럼이 이름 나이 학력이지만 A1의 변수는 이름, 나이만 있을 수도 있다 혹은 다른 것들이 담길 수도 있다.
  • 필요에 따라 한 테이블에 기반한 여러 엔티티를 만들 수도 있다.

EntityManager

  • 쉽게 말하자면 말 그대로 엔티티들을 관리하는 클래스
  • 어떻게 관리하는가? 바로 엔티티 매니저 클래스에서 영속성 컨텍스트라는 것을 두어 엔티티들을 관리한다. -

영속성

- 비휘발성의 반대말이다. 서버나 컴퓨터가 종료되어도 데이터가 남는 성질을 의미한다.
- 보통 저장장치(ssd, hdd, 메모리 등등)에서는 휘발성, 비휘발성이라고 개념명을 붙이고 DB에서는 이러한 개념을 영속성이라는 이름으로 부른다.

컨텍스트

- 데이터가 담기는 어떤 가상의 공간으로 이해하자

영속성 컨텍스트

  • 즉 엔티티 매니저가 초기화된다던지 종료되어버리지 않는 이상 엔티티를 장기간 보관하기 위한 공간, 환경을 나타내는 말
  • Spring에서는 굉장히 복잡하고 무수히 많은 코드의 API로 기능이 실행되기에 하나하나 뜯어볼게 아닌 이상 하나의 추상적 개념으로만 이해하자
  • 여러 엔티티매니저가 하나의 영속성 컨텍스트를 공유할 수도 있다.

영속성 컨텍스트의 구성

1차 캐시

- 만약 commit하기전 데이터는 어디로 담겨있을까?
- 바로 DB로 이동하는 것이 아닌 영속성 컨텍스트 내부에 있는 저장소 "1차캐시"로 이동한다.
- 트랜잭션이 시작하고 끝날 때까지만 해당 1차캐시가 유효하다.
- Set에서 처럼 같은 엔티티가 있다면 중복 저장은 되지 않는다.(객체 동일설 보장 ==)
- 만약 find와 같은 명령을 호출하면 해당 데이터를 우선 1차 캐시에서 찾아 반환한다.만약  없다면 DBdptj 데이터를 찾는다.  
2차캐시
- 동시성(Concurrency)을 보다 강화하기 위해서 쓰는 개념
- 애플리케이션에서 공유하는 캐시를 JPA에서는 공유캐기(shared cache)라고 하며 2차캐시(second level cach, L2 cache)라고 부른다.
- 2차 캐시는 어플리케이션이 종료할 때까지 유지된다.
- 엔티티 매니저가 데이터를 조회할 때 2차캐시를 먼저 확인하고 찾는 데이터가 없다면 그때 DB를 확인한다.
- 1차 캐시에서 데이터가 없다면 2차캐시를 2차캐시에도 없다면 DB를 확인하는 것
- 2차 캐시를 갖고있는 데이터를 반환할 때 해당 데이터의 원본이 아닌 복사본을 반환한다.
- 왜냐하면 나중에 다른 곳에서 같은 데이터를 요청할 때 해당 객체를 동시에 수정할 수도 있기 때문.
  - 이를 방지하고자 원본을 주고 대신 Lock을 걸면 동시성에 문제가 생긴다. 이러한 매커니즘으로 동시성이 극대화되는 것
- 1차와 달리 2차는 애플리케이션 전체에 해당하는 범위를 커버하기에 1차 캐시 기능을 넘어 보다 넒은 커버링으로 데이터베이스에 조회를 하는 작업이 훨씬 줄어들게 된다.

<img src="..\images\1차캐시vs2차캐시.png" width="600px" height="400px"/>

쓰기 지연 SQL 저장소

  • 영속성 컨텍스트의 2번쨰 영역으로 persist()를 통해 영속성 컨텍스트에 들어온 데이터들(엔티티)에 대한 SQL명령어즉 쿼리문이 저장되는 공간이다.
  • 트랜잭션이 커밋되기 전에는 이곳에 쿼리문이 계속 저장된다.

쓰기 지연 SQL 저장소의 목적

  • 이렇게 쿼리문을 따로 저장하는 이유는 무엇인가?
  • 만약 회원의 정보를 변경한다고 할 때, 회원 1의 이름과 회원 2의 전화번호를 바꾸는 하나의 트랜잭션을 진행한다고 가정해보자.
       tx.begin();
    
              em.persist(member);
              em.persist(member2);
    
       tx.commit();
    
  • 회원 1은 아무런 문제 없이 변경된 엔티티를 1차 캐시로 보내고 쿼리문도 sql저장소에 저장했다
  • 근데 회원 2의 전화번호가 양식과 맞지 않아 예외가 발생하여 롤백을 해야한다.
  • 만약 쓰기 지연 Sql 저장소가 없었다면? 회원1의 변경사항에 대한 쿼리문(회원정보 수정이니 update 명령어일 것이다(아마도))이 바로 DB로 전달되 DB가 바뀌었을 것이고 그러면 다시 DB에 이전으로 되돌리는 롤백을 DB에서 다시 진행해야할 것이다.
  • 때문에 이러한 사고를 방지하고자 쓰기 지연 SQL 저장소를 두어 커밋되기전에는 DB에 변경사항이 적용되지 않도록 방지하는 것이다. - 쉽게 말해 어플리케이션에서 발생한 예외를 어플리케이션 내부에서 처리하도록(즉 롤백을 내부에서 처리) 막아 둔 것이다.

EntityManagerFactory

- 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 생기기에 스레드끼리는 한의 엔티티 매니저를 공유할 수 없다(즉 하나의 영속성컨텍스트레 여러 쓰레드가 동시에 자료를 요청할 수 없다는 것)
- 그러면 하나의 엔티티 매니저가 가진 영속성 컨텍스트의 데이터를 모두가 써야만 한다면 어떻게 할까?
- 그럼 해당 엔티티 매니저를 여러개 만들면된다. 1 쓰레드 1엔티티매니저
- 이렇게 말 그대로 엔티티매니저 객체를 만들어내는 기능을 하는 것이 바로 EntityManagerFactory이다.
```java
EntityManagerFactory em =  emFacotry.createEntityManager();
```
- 이 엔티티매니저팩토리라는 공장에서 엔티티 매니저를 만들어낸다.
- 따라서 여러 쓰레드가 접근할 때는 엔티티 매니저가 아닌 엔티티매니저팩토리에 접근하면 된다.
- 주의점은 엔티티매니터팩토리는 DB당 하나만 사용가능하다는 것.

카테고리:

업데이트:

댓글남기기