OSIV ( ⭐⭐⭐ )

타마타마·2022년 10월 5일
0

JPA

목록 보기
10/10

OSIV란?

Open Session In View
application.yml의 spring.spa.open-in-view: ture -> 기본값

spring 기본 로직

트랜잭션 시작할 때 DB 커넥션 가져옴 -> 트랜잭션이 끝난 후에도 DB 커넥션을 가지고 있음
(osiv : true 인 경우)

why?

지연로딩일 때 실 엔티티 사용하기 위해서 영속성컨텍스트가 가지고 있는 객체를 사용해야 하기 때문.

OSIV란? >> 트랜잭이 시작 할 때 DB커넥션 가져와 시작 ~ API응답 끝날 때까지 영속성 컨텍스트에 DB 커넥션 유지 한 것

이로인해 너무 오래 DB 커넥션을 물고 있는 경우가 생긴다면 실시간 트래픽 사용할 때 장애가 발생할 수 있음

OSIV 장애 해결법

application.yml > spring.jap.open-in-view : false 설정

트랜잭션 끝나기 전에 지연로딩 로직 처리하자 ! == Controller는 영속성 컨텍스트에 포함

이때 잘못 사용하게 된다면 : org.hibernate.LazyInitializationException : could not initialize proxy 오류 발생

따라서

커멘드와 쿼리 분리할 것
Service : 핵심 비즈니스 로직 ( controller와 service관계일 때와 다름 없음 )
QueryService : API에 맞춘 서비스로 읽기전용 트랜잭션 (readonly=true)

Controller

단순 쿼리서비스 쪽 호출만 함.

@RestController
@RequiredArgsConstructor
public class OrderApiController {
   //................

private final OrderQueryService orderQueryService;


    @GetMapping("/api/v3/orders")
    public List<OrderDto> orderV3() {
      return orderQueryService.orderV3; // 단순 호출
    }

  //................

}

QueryService ( QueryOrderItem )

실제 API통신을 해줌

@RestController
@RequiredArgsConstructor
public class OrderApiController {

    @GetMapping("/api/v1/orders")
    public List<Order> ordersV1() {
        List<Order> all = orderRepository.findAll(new OrderSearch());

        // 지연 로딩을 시도한다.
        for (Order order : all) {
            order.getMember().getName();
            order.getDelivery().getAddress();
            List<OrderItem> orderItems = order.getOrderItems();
            orderItems.forEach(o -> o.getItem().getName());
        }

        return all;
    }
}

Service ( OrderItem )

핵심 비즈니스 로직 처리

결론

실시간 API사용량 많을 땐 OSIV : false !
커넥션 사용이 없을 땐 OSIV : true !

0개의 댓글