Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- AOP
- spring
- 인프런
- 스프링 핵심 기능
- JPQL
- Greedy
- 백준
- 스프링 핵심 원리
- SpringBoot
- 알고리즘
- java
- pointcut
- jpa
- db
- Android
- 스프링
- 그리디
- Proxy
- Servlet
- Thymeleaf
- Spring Boot
- springdatajpa
- Exception
- JDBC
- kotlin
- 김영한
- QueryDSL
- transaction
- 자바
- http
Archives
- Today
- Total
개발자되기 프로젝트
지연 로딩과 조회 성능 최적화(JPA에서 DTO 바로 조회) 본문
1. Controller
@GetMapping("/api/v4/simple-orders")
public List<OrderSimpleQueryDto> ordersV4(){
return orderRepository.findOrderDtos();
}
2. Repository
- JPA에서 DTO를 바로 조히하는 방법
- new 명령어를 사용해서 JPQL결과를 DTO로 즉시 변환.
- Query안에 DTO를 생성하여 값을 직접 넣어줌.
public List<OrderSimpleQueryDto> findOrderDtos() {
return em.createQuery(
"select new springjpa2.repository.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address) " +
"from Order o " +
"join o.member m " +
"join o.delivery d", OrderSimpleQueryDto.class)
.getResultList();
}
3. DTO
@Data
public class OrderSimpleQueryDto {
private Long orderId;
private String name;
private LocalDateTime orderDate;
private OrderStatus orderStatus;
private Address address;
public OrderSimpleQueryDto(Long orderId, String name, LocalDateTime orderDate, OrderStatus orderStatus, Address address){
this.orderId = orderId;
this.name = name;
this.orderDate = orderDate;
this.orderStatus = orderStatus;
this.address = address;
}
}
4. 쿼리 비교
- V3 : FETCH JOIN
- SELECT쿼리에 뭐가 많음..
- 대신 내가 원하는 값만 가져옴.
- 외부로 보낸 타입을 변경하지 않음.
- FETCH JOIN의 결과는 여러 API에서 사용 가능. -> 원하는 DTO로 변경
Hibernate:
select
order0_.order_id as order_id1_6_0_,
member1_.member_id as member_i1_4_1_,
delivery2_.delivery_id as delivery1_2_2_,
order0_.delivery_id as delivery4_6_0_,
order0_.member_id as member_i5_6_0_,
order0_.order_date as order_da2_6_0_,
order0_.status as status3_6_0_,
member1_.city as city2_4_1_,
member1_.street as street3_4_1_,
member1_.zipcode as zipcode4_4_1_,
member1_.name as name5_4_1_,
delivery2_.city as city2_2_2_,
delivery2_.street as street3_2_2_,
delivery2_.zipcode as zipcode4_2_2_,
delivery2_.status as status5_2_2_
from
orders order0_
inner join
member member1_
on order0_.member_id=member1_.member_id
inner join
delivery delivery2_
on order0_.delivery_id=delivery2_.delivery_id
- V4 : DTO 직접 조회
- SELECT쿼리로 선택하는 데이터가 훨씬 적음.
- 원하는 값을 선택에서 조회 가능.
- 해당 DTO를 사용할 때만 사용 가능한 쿼리임.
- 해당 REPOSITORY 재사용성이 적음.
- 결국 API SPEC으로 REPOSITORY를 만든 것.
- API 변경되면 REPOSITORY가 변경되어야함.. ㅜ
- 단 성능최적화 부분에서는 V3보다는 좋음...ㅎ
- DTO로 조회했기 때문에 엔티티 변경 불가능.
Hibernate:
select
order0_.order_id as col_0_0_,
member1_.name as col_1_0_,
order0_.order_date as col_2_0_,
order0_.status as col_3_0_,
delivery2_.city as col_4_0_,
delivery2_.street as col_4_1_,
delivery2_.zipcode as col_4_2_
from
orders order0_
inner join
member member1_
on order0_.member_id=member1_.member_id
inner join
delivery delivery2_
on order0_.delivery_id=delivery2_.delivery_id
5. V3, V4 성능차이 클까???
- 대부분의 성능 차이는
- join, where 조건 등에서 차이가 주된 요인이지 필드 추가는 큰 영향 없다.
6. Repository는 최대한 entity를 조회하기 위해서 사용해야 한다.
- 현재 v4는 API 스펙이 repository에 반영되어 엔티티가 아닌 dto를 조회한다..
- 보완이 필요.
- repository 패키지 하위에 query용 package를 추가
- 기존 dto 조회관련 class 이동 ㅋㅋㅋ
7. 정리
엔티티를 DTO로 변환하거나 DTO로 바로 조회하는 두 가지 방법은 장단점 있음.
엔티티로 조회하면 Repository 재사용성이 좋고, 개발도 단순함
- 쿼리 방식 선택 권장 순서
- 우선 엔티티를 DTO로 변환하는 방법을 선택
- 필요하면 FETCH JOIN으로 성능 최정화
- 그래도 안된다면 DTO 직접 조회
- 최후의 방법은 JPA가 제공하는 Native SQL, JDBC Template 사용하여 SQL직접 사용
8. GitHub : 210822 JPA에서 DTO 조회
'인프런 > [인프런] Springboot와 JPA활용 2' 카테고리의 다른 글
컬렉션 조회 최적화 : fetch join 적용 (0) | 2021.08.24 |
---|---|
컬렉션 조회 최적화 (0) | 2021.08.24 |
지연 로딩과 조회 성능 최적화(FETCH JOIN) (0) | 2021.08.22 |
지연로딩과 성능최적화(DTO, N+1) (0) | 2021.08.22 |
지연로딩과 조회성능 최적화(엔티티 노출) (0) | 2021.08.22 |
Comments