2단계 음식 등록문제
- 음식점 ID 및 음식 정보 입력받아 등록
- 음식점 ID (restaurantId)
- 음식점 DB 테이블 ID
- 음식명 (name)
- 같은 음식점 내에서는 음식 이름이 중복될 수 없음 (예. '자담치킨 강남점'에 '후라이드치킨' 이 이미 등록되어 있다면 중복하여 등록할 수 없지만, 다른 음식점인 '맘스터치 강남점'에는 '후라이드치킨' 을 등록 가능)
- 가격 (price)
- 허용값: 100원 ~ 1,000,000원
- 100 원 단위로만 입력 가능 (예. 2,220원 입력 시 에러발생. 2,300원 입력 가능)
- 허용값이 아니거나 100원 단위 입력이 아닌 경우 에러 발생시킴
- 음식점 ID (restaurantId)
- 메뉴판 조회
- 하나의 음식점에 등록된 모든 음식 정보 조회
- 등록 시 입력한 음식 정보 (name, price)
- DB 테이블 ID (id)
- 하나의 음식점에 등록된 모든 음식 정보 조회
API 명세서
API Path | Request Body Sample | Response Body Sample | |
음식 등록 | POST /restaurant/{restaurantId}/food/register | [ { name: "쉑버거 더블" price: 10900 }, { name: "치즈 감자튀김" price: 4900 }, { name: "쉑버거 더블" price: 5900 } ] |
|
메뉴판 조회 | GET /restaurant/{restaurantId}/foods | [ { id: 1 name: "쉑버거 더블" price: 10900 }, { id: 2 name: "치즈 감자튀김" price: 4900 }, { id: 3 name: "쉑버거 더블" price: 5900 } ] |
POST ->
대괄호 [] : 리스트
중괄호 {} -> 3개
각각은 음식명(name)과 음식가격(price)이 있음
문제점
API의 Controller 부분에서 설계 문제로, 400오류가 발생 -> 설계를 잘못 함
API의 url 주소는 문제가 없지만, public의 registerFood에 들어갈
@RequestBody와 @Pathvariable(url로 입력받는 restaurantId을 받아 줌)을 넣어주는 부분이 빠져있음
해결과정
1. @RequestBody의 FoodDto가 어떻게 구성되어 있는지 보자
우리가 음식을 등록하는데 있어
ㄱ. 음식명 (name)
ㄴ. 음식가격 (price)
라는 하나의 정보 만을 받고 있다.
FoodDto를 통해서 받아야 할 것이 3개의 음식이기 때문에,
List<FoodDto>으로 바꿔줘야 한다.
2. restaurantId가 주소값에서 들어오고 있다. -> /{restaurantId}/
이걸 받아주기 위해서는, @RequestBody로 받는게 아니라 @Pathvariable을 넣어줘야함
->@PathVariable Long restaurantId
-> 이때 FoodDto에 입력해 두었던 restaurantId는 필요가 없기 때문에 지워주자
음식이름 & 음식가격 ->@RequestBody List<FoodDto> requestDto
// 하나가 Fooddto이고, 이것을 여러개 받기 위해서는 List형식으로 받아야 함
Url을 통해 받는 restaurantId -> @Pathvariable Long restaurantId
// @PathVariable url을 통해서 값을 받는다
3. Dto의 형태가 바뀌어서 Service도 바꿔줘야 함
public Food registerFood 다음에 FoodDto 하나만 들어오는게 아니라 List<Food>로 들어오고,
resturantId도 함께 넣어 줘야 함
또한, restaurantId를 이미 받았기 떄문에, 퍼블릭 내용에서 지워 주었다.
이때, 컨트롤러에서 서비스로 보내주는 값을 추가한다.
foodService.registerFood(requestDto, restaurantId)
3-1. requestDto가 여러개의 리스트 형식으로 들어가 있는 것을 For문으로 하나씩 뽑아내 줘야 됨
for(int i = 0; i < requestDtos.size(); i++) {
FoodDto requestDto = requestDtos.get(i);
각 이름과 가격은 requestDto.getName();과 getPrice를 통해서 값을 뽑아내 준다.
그 다음은 테스트 조건문을 Food registerFood안에 넣어 준다.
3-2. 음식 등록이기 때문에, 리턴값이 필요없음 -> public void로 바꾼다
ㄱ. public void 로 변경
ㄴ. 리턴값이 없기 때문에 Food registerFood에서 Food를 지운다 (반환 타입이 없으므로)
ㄷ. return food 삭제
4. Food 엔티티 (entity)을 보자
public Food(Long restaurantId, String name, Long price) {
this.restaurantId = restaurantId;
this.name = name;
this.price = price;
}
5. 테스트
테스트 결과 음식이 등록이 되었다.
그리고 Food의 entity부분에서
음식점에 음식을 등록하는 API를 설계하는데 어려움을 느겼습니다. (기초가 부족하여 어떻게 설계하는지 헤맴)
<추가 내용>
1. 용도를 알아보자! - 어떨 때 쓰는가?
@RequestBody :
-> http요청의 본문(body)이 그대로 전달
-> xml이나 json기반의 메시지를 사용하는 요청의 경우에 이 방법이 매우 유용하다.
https://cheershennah.tistory.com/179
@Pathvariable :
- > URL을 처리할 때는 @PathVariable을 사용
https://2ham-s.tistory.com/290
2. 파라미터
순서대로 넣고, 순서대로 받는다.
위 3가지를 넣었으니, 3가지를 넣어줘야 실행이 됨
3. JPA
findAll? 이런거는 어떤건가?
-> extends JpaRepository
extends : 상속이라는 개념 - 누가 미리 만들어 놓을 것을 받는다 / 쉽게 쓰라고 미리 만들어 놈
findAll / findAllbyId 등 미리 만들어져 있고,
기본으로 만들어 져 있기 때문에 생략도 가능함.
-> Service에서 save가 근야 쓸 수 있음
ㄱ. RestaurantRepository과 ServiceRestaurant 연결됨
-> @RequiredArgsConstrouctor : private final이라는 접근제한자가 되어있으면,
자동으로 DI(dependency Injection) 외부요소들(만들어 져있는 것을)을 삽입해줌
https://medium.com/@jang.wangsu/di-dependency-injection-%EC%9D%B4%EB%9E%80-1b12fdefec4f
-> 따라서 내가 RestaurantRepository를 만들어 놨기 때문에 이 내용을 Service에서 가져와서 쓸 수 있게 해준다.
@RequiredArgsConstructor
@Service
public class RestaurantService {
private final RestaurantRepository restaurantRepository;
ㄴ.save도 상속으로 사용할 수 있다.
restaurantRepository.save(restaurant);
정리
1. 어노테이션의 용도
@RequestBody :
-> http요청의 본문(body)이 그대로 전달
-> xml이나 json기반의 메시지를 사용하는 요청의 경우에 이 방법이 매우 유용하다.
https://cheershennah.tistory.com/179
@Pathvariable :
- > URL을 처리할 때는 @PathVariable을 사용
https://2ham-s.tistory.com/290
2. 상속
extends : 상속이라는 개념 - 누가 미리 만들어 놓을 것을 받는다 / 쉽게 쓰라고 미리 만들어 놈
findAll / findAllbyId 등 미리 만들어져 있고,
기본으로 만들어 져 있기 때문에 생략도 가능함.
-> Service에서 save가 근야 쓸 수 있음
@RequiredArgsConstrouctor : private final이라는 접근제한자가 되어있으면,
자동으로 DI(dependency Injection) 외부요소들(만들어 져있는 것을)을 삽입해줌
https://medium.com/@jang.wangsu/di-dependency-injection-%EC%9D%B4%EB%9E%80-1b12fdefec4f
-> 따라서 내가 RestaurantRepository를 만들어 놨기 때문에 이 내용을 Service에서 가져와서 쓸 수 있게 해준다.
'공부 > 메모' 카테고리의 다른 글
JPA의 @Enumerated를 알아보자 - 1 (0) | 2022.04.16 |
---|---|
[cs공부] 미들웨어(Middleware) - 2 (0) | 2022.04.15 |
[cs공부] 미들웨어(Middleware) - 1 (0) | 2022.04.15 |
스프링 심화과정 - 순한맛 2단계 음식조회, 중복 (0) | 2022.04.05 |
자바문법 메모 01 (0) | 2022.04.03 |