1. 테이블 구조
현재 위와 같은 구조로 테이블이 정의되어 있다. trip과 itinerary가 1 : N 관계이다.
RFP에 나와 있는 trip 조회 API의 요구사항에는
위와 같이 여행을 조회할때 여정의 이름들을 함께 보여주도록 되어 있다.
나는 조금 변형하여 특정 여행을 조회할때 여정 이름들을 함께 보여주도록 구현해보았다.
2. Service 계층 로직
로직이 수행되는 서비스 계층의 메서드이다.
동작하는 방식을 살펴보면 매개변수로 넘어온 tripId로 DB에 여행이 존재하는지를 먼저 확인한 후에, 없다면 예외를 반환한다.
(RuntimeException을 던지도록 임시로 구현했다.)
그리고 여행이 존재하면 반환한 trip 엔티티 인스턴스를 DTO로 변환해야 한다.
3. FetchType.EAGER와 FetchType.LAZY의 차이
이 로직에서 바로 엔티티 클래스에 어노테이션으로 붙이는 FetchType.EAGER와 FetchType.LAZY의 차이가 발생한다.
즉시로딩과 지연로딩은 참조관계에 있는 엔티티를 말그대로 즉시 로딩할 것인지, 아니면 정말 참조가 필요한 런타임에 참조할 것인지를 결정한다.
실제 Spring Data JPA에서 날리는 쿼리문을 캡쳐해서 각각 비교해 보았다.
즉시로딩으로 설정했을 때는, 여정을 기준으로 Left Join을 수행한다. 즉, 일단 참조관계에 있는 테이블들을 조인으로 다 엮어서 한방에 불러오는 것이다.
참조관계가 복잡하거나, 사용해야할 속성이 많지 않을 때 즉시로딩을 수행하면 비용이 많이 들기 때문에 실무에서 많이 사용되지는 않는다고 한다.
오른쪽은 지연로딩을 했을때의 쿼리문이다. findById를 사용하여 일단 tripId로 여행을 찾은 다음, 여정의 이름을 ArrayList에 담아야 하는 구문에 실행되면 그제서야 여정을 조회하는 select 문을 날리게 된다.
김영한님이 JPA 책을 읽는 중인데, 실무에서는 LAZY로 거의 고정시켜놓고 사용한다고 한다.
지연로딩의 특징은 일단 엔티티 객체와 구조가 똑같은 프록시 객체를 만들어놓는다고 한다. 이 프록시 객체는 실제 엔티티 객체를 참조하고 있어서 런타임에 특정 getter로 값을 불러와야하면 그제서야 값을 불러온다고 한다.
아직 정확히는 모르지만 JPA에 대한 이해도가 점점 깊어지는 것 같다. 열심히 하자
'Spring' 카테고리의 다른 글
[Spring] Static Method를 Mocking Test 하는 방법 (0) | 2023.11.19 |
---|---|
[JPA] fetchType.EAGER(즉시로딩)의 N+1문제의 원인과 해결방법 (1) | 2023.11.09 |
[JPA]JPA 양방향 매핑 (0) | 2023.10.31 |
예외처리 - Exception Handle (0) | 2023.10.28 |
[SpringBoot] BindException 해결법 (0) | 2023.08.26 |