반응형
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 |
Tags
- 스프링
- 플러터 개발
- 기술면접공부
- DDD
- JPA
- 스프링부트공부
- 코테공부
- 프로그래머스
- Axon framework
- JPA예제
- nestjs
- querydsl
- JPA공부
- K8S
- 자바공부
- Flutter
- JPA스터디
- 스프링 공부
- nestjs스터디
- nestjs공부
- 알고리즘공부
- 자료구조공부
- 플러터 공부
- 스프링공부
- 코테준비
- JPA 공부
- 스프링부트
- 카프카
- Kafka
- 기술공부
Archives
- Today
- Total
DevBoi
[JPA] Nested Response List 처리 본문
반응형
상속 적으로 Response가 필요한 경우가 있다.
부모 DTO가 있고 해당 디티오는 하위의 디티오 리스트를 가지고 있다.
해당 케이스는 아래와 같이 처리한다.
package com.boiler.core.backend.normaladmin.reservation.dto;
import com.boiler.core.backend.entity.Gym;
import com.boiler.core.backend.entity.Member;
import com.boiler.core.backend.entity.Reservation;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class NormalReservationListResponse {
Member trainer;
List<NormalReservationDetailResponse> info;
}
package com.boiler.core.backend.normaladmin.reservation.dto;
import com.boiler.core.backend.entity.Member;
import com.boiler.core.backend.entity.Reservation;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class NormalReservationDetailResponse {
Reservation reservation;
Member member;
}
물론 엔티티를 내리는게 정상적인 방법은 아니지만, 단순 조회용이나 Response를 내리는것들은
영속성 컨텍스트가 어차피 끊어지기 때문에 딱히 위험하지 않다.
public List<?> getGymReservationList(NormalReservationDto normalReservationDto){
QMember trainer = new QMember("trainer");
return queryFactory
.from(reservation)
.leftJoin(trainer).on(trainer.id.eq(reservation.trainerId))
.leftJoin(member).on(member.id.eq(reservation.memberId))
.where(
reservation.gymId.eq(normalReservationDto.gymId()),
reservation.useDate.between(
normalReservationDto.date(),
normalReservationDto.date().plusDays(1))
)
.transform(groupBy(trainer.id)
.list(Projections.constructor(NormalReservationListResponse.class,
trainer.as("trainer"),
list(Projections.fields(NormalReservationDetailResponse.class,
member.as("member"),
reservation.as("reservation")
)
)
))
)
.stream().toList();
}
해당 과 같이 하면 아래와 같은 결과를 얻는다.
[
{
"trainer": {
"createDate": "2023-09-29T23:56:52.909215",
"modifiedDate": "2023-09-29T23:56:52.909215",
"id": 2,
"userId": "asdfadsf",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "10",
"snsCode": "string",
"status": "10",
"memo": "string"
},
"info": [
{
"reservation": {
"createDate": "2023-09-26T22:41:58.260999",
"modifiedDate": "2023-09-26T22:41:58.260999",
"id": 1,
"memberId": 1,
"trainerId": 2,
"status": "10",
"gymId": 1,
"useDate": "2023-09-26T13:41:51.966",
"memo": "string",
"cancleCaus": "string",
"ticketIssueId": 1,
"reservationName": "string",
"reservationPhone": 0
},
"member": {
"createDate": "2023-09-27T21:14:55.854566",
"modifiedDate": "2023-09-27T21:14:55.854566",
"id": 1,
"userId": "smith123",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "string",
"snsCode": "string",
"status": "10",
"memo": "string"
}
}
]
},
{
"trainer": {
"createDate": "2023-09-29T23:56:57.495662",
"modifiedDate": "2023-09-29T23:56:57.495662",
"id": 3,
"userId": "vzxcvzxv",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "20",
"snsCode": "string",
"status": "10",
"memo": "string"
},
"info": [
{
"reservation": {
"createDate": "2023-09-26T22:42:01.285291",
"modifiedDate": "2023-09-26T22:42:01.285291",
"id": 4,
"memberId": 1,
"trainerId": 3,
"status": "10",
"gymId": 1,
"useDate": "2023-09-26T13:41:51.966",
"memo": "string",
"cancleCaus": "string",
"ticketIssueId": 1,
"reservationName": "string",
"reservationPhone": 0
},
"member": {
"createDate": "2023-09-27T21:14:55.854566",
"modifiedDate": "2023-09-27T21:14:55.854566",
"id": 1,
"userId": "smith123",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "string",
"snsCode": "string",
"status": "10",
"memo": "string"
}
}
]
},
{
"trainer": {
"createDate": "2023-09-29T23:56:52.909215",
"modifiedDate": "2023-09-29T23:56:52.909215",
"id": 2,
"userId": "asdfadsf",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "10",
"snsCode": "string",
"status": "10",
"memo": "string"
},
"info": [
{
"reservation": {
"createDate": "2023-09-26T22:42:01.431401",
"modifiedDate": "2023-09-26T22:42:01.431401",
"id": 5,
"memberId": 1,
"trainerId": 2,
"status": "10",
"gymId": 1,
"useDate": "2023-09-26T13:41:51.966",
"memo": "string",
"cancleCaus": "string",
"ticketIssueId": 1,
"reservationName": "string",
"reservationPhone": 0
},
"member": {
"createDate": "2023-09-27T21:14:55.854566",
"modifiedDate": "2023-09-27T21:14:55.854566",
"id": 1,
"userId": "smith123",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "string",
"snsCode": "string",
"status": "10",
"memo": "string"
}
},
{
"reservation": {
"createDate": "2023-09-26T22:43:46.185942",
"modifiedDate": "2023-09-26T22:43:46.185942",
"id": 6,
"memberId": 1,
"trainerId": 2,
"status": "10",
"gymId": 1,
"useDate": "2023-09-26T13:41:51.966",
"memo": "string",
"cancleCaus": "string",
"ticketIssueId": 1,
"reservationName": "string",
"reservationPhone": 0
},
"member": {
"createDate": "2023-09-27T21:14:55.854566",
"modifiedDate": "2023-09-27T21:14:55.854566",
"id": 1,
"userId": "smith123",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "string",
"snsCode": "string",
"status": "10",
"memo": "string"
}
},
{
"reservation": {
"createDate": "2023-09-26T22:43:46.688126",
"modifiedDate": "2023-09-26T22:43:46.688126",
"id": 7,
"memberId": 1,
"trainerId": 2,
"status": "10",
"gymId": 1,
"useDate": "2023-09-26T13:41:51.966",
"memo": "string",
"cancleCaus": "string",
"ticketIssueId": 1,
"reservationName": "string",
"reservationPhone": 0
},
"member": {
"createDate": "2023-09-27T21:14:55.854566",
"modifiedDate": "2023-09-27T21:14:55.854566",
"id": 1,
"userId": "smith123",
"userPw": "dfjeisn!",
"imgUrl": "string",
"nickname": "string",
"name": "string",
"gender": "string",
"introduce": "string",
"birth": "string",
"phone": "string",
"address": "string",
"email": "string",
"authCode": "string",
"snsCode": "string",
"status": "10",
"memo": "string"
}
}
]
}
]
트레이너 기준으로 하위 member,resevation 정보를얻는것이다.
이렇게 하면 간단하게 구현가능하다.
JPA를 사용하다 보면 Entity를 내리는 것에 대해 부정적인 개발자들이 많다.
내 개인적인 생각으로는 정보 요청용은 DTO로 받고 이를 변환시켜서 엔티티로 넣고
그외 조회는 엔티티를 그대로 내려도 무방하다고 생각한다.
엔티티를 조심하는건 Persist context를 통해 의도치 않은 디비 변경때문이라고 생각하는데
조회에서 해당 값을 변환하거나 수정하는 경우는 거의 없다.
무작정 Entity를 레이어간 분리하자! 는 좀 ;; 억까스러운 개발자 매너리즘으로 보인다.
반응형
'Develop > [JPA]' 카테고리의 다른 글
[JPA] 스프링 Timezone 설정 + Aws, Docker mariadb timezone설정 (0) | 2023.09.30 |
---|---|
[QueryDsl] Spring 3 버전 p6spy 적용 (0) | 2023.09.09 |
[JPA] Querydsl & Paging (0) | 2023.09.02 |
[JPA] JPAUpdateClause 사용 (0) | 2023.09.02 |
[Jpa] Querydsl build Setting (0) | 2023.09.02 |