JPA에서 EntityManager가 하이버네이트에서는 Session이다. (예전엔 하버네이트만 있었다.)
영속성컨텍스트는 동작을 하려면 DB커넥션을 내부적으로 사용을 해야 lazy로딩을하든 뭘 하든 할 수 있다. 그래서 영속성컨텍스트와 DB커넥션은 굉장히 밀접하게 매칭이 되어있다. 영속성 컨텍스트는 DB커넥션을 1:1로 쓰면서 동작해야함.
언제 JPA가 DB커넥션을 획득을 하냐 -> 기본적으로 DB트랜젝션 시작할 때 JPA의 영속성컨텍스트가 DB커넥션을가져옴.
-> DB커넥션 언제 돌려줘야 할까 (이 시점이 중요) ->
서비스레이어에서 트랜젝션 시작할 때 DB커넥션 가져온다. osiv가 꺼져있다면 트랜젝션붙은 메서드가 끝날 때 트랜젝션이 닫히면서 영속성컨텍스트 또한 닫히게 된다. 만약 osiv 켜져있으면 @Transactional 끝나고 컨트롤러 밖으로 나가도 DB커넥션을 반환을 안함. -> 왜 안하냐? -> controller에서 lazy로딩으로 가져오기위해.
여기서도 80줄에서 order를 가져오고 82줄에서
여기의 .getMember().getName() 나 .getDelivery().getAdress() 할 때 member, delivery가 LAZY 로딩 일어나서 프록시객체를 실제 객체로 채워야(초기화) 하기 때문에 영속성 컨텍스트가 DB커넥션을 물고 살아있어야함. -> OSIV : 트랜잭션이 끝나도 영속성 컨텍스트를 API응답이 될 때까지 , view라면 viewTemplate 가지고 렌더링할 때까지.
: 모두 응답하여 더이상 필요없는 단계까지 DB커넥션을 물고 있는다. (영속성 컨텍스트와 DB커넥션은 한 세트로 기억하자.)
--> 하지만 이 전략의 최대 단점. -> 너무 오래동안 DB커넥션을 물고 있는다. -> 실시간 트래픽이 중요한 애플리케이션의 경우 커넥션이 모자랄 수 있다. (= 커넥션이 말라버린다.) -> 결국 장애.
장점 : 컨트롤러나 뷰에서 지연로딩 할 수 있다.
#OSIV 껐을 때
이러면 트랜잭션 끝날 때 DB커넥션도 끊는다. -> 이후 컨트롤러에서 죽어도 못쓴다.
지연로딩을 하려면 당연하게도 영속성컨텍스트가 살아있어야함.
OSIV 껐을 때 트랜젝션 밖에서 지연로딩하면
LazyInitializationException 터진다. cound not initial proxy
이 때 방법(중요하므로 하나하나 생각)
1. OSIV를 킨다.
2. 트랜잭션 내부에서 지연로딩을 다 시켜놓는다.
3. fetch join 으로 애초에 한번의 쿼리로 지연로딩할 객체를 다 가져온다.
4. 따로 Service를 만들어서 Controller의 변환코드들을 들고간다.
위의 컨트롤러의 로직을 트랜잭션을 연 service로 데려와서 컨트롤러에 반환한다.
핵심 비지니스로직이 있는 service와 분리하자.
-> 이건 영한님이 선호하는 방법.
-> 이게 커맨드와 쿼리를 분리하는 방법이다.
결론 : 고객서비스기반의 트래픽이 많은 실시간 API를 많이 제공해야하는 API 서버의 경우 OSIV를 꺼논다.
이럴 경우 안끄면 커넥션풀 다 말라버린다. , ADMIN 처럼 커넥션을 많이 사용하지 않는 곳에서는 OSIV를 켠다.
(보통 ADMIN서버, API서버를 배포를 따로 하므로)
'Java, Spring > 스프링부트와 JPA 활용 2' 카테고리의 다른 글
4-8. 총정리(API 개발 고급 정리) (0) | 2022.09.12 |
---|---|
4-7. 주문 조회 V6: JPA에서 DTO로 직접 조회, 플랫 데이터 최적화 (1) | 2022.09.11 |
4-6. 주문 조회 V5: JPA에서 DTO 직접 조회 - 컬렉션 조회 최적화 (0) | 2022.09.11 |
4-5. 주문 조회 V4: JPA에서 DTO 직접 조회 (1) | 2022.09.11 |
4-4. 주문 조회 V3.1: 엔티티를 DTO로 변환 - 페이징과 한계 돌파 (아주아주아주아주아주 중요) (2) | 2022.09.10 |