문제
1.2. 음식점 상세 조회
특정 음식점의 상세 정보와 메뉴 목록을 조회하는 API입니다.
- URL: /api/v1/restaurants/{id}
- Method: GET
- 설명:
- 음식점의 기본 정보를 제공합니다.
- 해당 음식점의 전체 메뉴 목록을 함께 반환합니다.
- 평균 평점과 총 리뷰 수를 포함합니다.
- 각 메뉴별 리뷰 수도 함께 제공됩니다.
- 존재하지 않는 음식점 ID인 경우 404 에러를 반환합니다.
- Response:
{
"restaurant": {
"id": 1,
"name": "맛있는 식당",
"category": "한식",
"address": "서울시 강남구",
"phone": "02-1234-5678",
"description": "전통 한식집",
"avgRating": 4.5,
"reviewCount": 100,
"createdAt": "2024-12-27T10:00:00",
},
"menus": [
{
"id": 1,
"name": "김치찌개",
"price": 8000,
"description": "돼지고기 김치찌개",
"category": "찌개",
"reviewCount": 50
}
]
}
2. 메뉴 API
2.1. 음식점별 메뉴 목록 조회
특정 음식점의 메뉴 목록을 조회하는 API입니다.
- URL: /api/v1/restaurants/{restaurantId}/menus
- Method: GET
- 설명:
- 특정 음식점의 전체 메뉴를 페이징 처리하여 제공합니다.
- 카테고리별 필터링을 지원합니다.
- 각 메뉴의 리뷰 수를 포함합니다.
- 메뉴는 카테고리별, 가격순으로 정렬 가능합니다.
- 존재하지 않는 음식점 ID인 경우 404 에러를 반환합니다.
- Query Parameters:
page: 페이지 번호 (기본값: 1)
size: 페이지 크기 (기본값: 10)
category: 메뉴 카테고리 필터 (선택)
sort: 정렬 기준 (price_asc, price_desc, name_asc)
- Response:
{
"content": [
{
"id": 1,
"name": "김치찌개",
"price": 8000,
"description": "돼지고기 김치찌개",
"category": "찌개",
"reviewCount": 50,
"createdAt": "2024-12-27T10:00:00"
}
],
"pageable": {
"page": 1,
"size": 10,
"totalElements": 50,
"totalPages": 5
}
}
풀이
1.2. 음식점 상세 조회
특정 음식점의 상세 정보와 메뉴 목록을 조회하는 API입니다.
- URL: /api/v1/restaurants/{id}
- Method: GET
Postman
- 설명:
- 음식점의 기본 정보를 제공합니다.
- 해당 음식점의 전체 메뉴 목록을 함께 반환합니다.
- 평균 평점과 총 리뷰 수를 포함합니다.
- 각 메뉴별 리뷰 수도 함께 제공됩니다.
- 존재하지 않는 음식점 ID인 경우 404 에러를 반환합니다.
intelliJ
@GetMapping("/api/v1/restaurants/{id}")
getRestaurantsId(@PathVariable long id) {
restaurantService.getRestaurantsId(id);
}
public RestaurantDetailListResponse getRestaurantsId(long id){
// if (!restaurantRepository.existsById(id)){
Optional<Restaurant> restaurant = restaurantRepository.findById(id);
if (restaurant.isEmpty()){
throw new RuntimeException();
}
// averageRating, reviewCount 를 구한다
// double avgRating = reviewRepository.findAvgRatingByRestaurantId(id);
// 위와 같이 Repository 에서 직접 구하는 방법도 있지만, 아래와 같이 직접 구하는 방법도 있다.
// 리뷰 카운트를 구한다.
int reviewCount = restaurant.get().reviewList.size();
int total = 0;
for(Review review : restaurant.get().reviewList){
total = total + review.rating;
}
double averageRating = (double) total / reviewCount;
// 정수 / 정수 = 정수 이기 때문에 double 로 형변환을 해준다.
service 의 개발 방법
1. JPQL 로 하는 방법
2. for 반복문으로 진행
위 두가지 방법이 있습니다. 위의 방식은 for 반복문으로 진행 하였습니다. JPQL 로 하는 방법로도 사용하는 방법에 대하여
전달 해 드리겠습니다.
@Data
@Entity
@Table(name = "restaurant")
public class Restaurant {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
@Column(length = 100)
public String name;
@Column(length = 200)
public String address;
@Column(length = 50)
public String phone;
@Column(length = 50)
public String category;
@Column(length = 200)
public String description;
@Column(length = 10)
public Instant createdAt;
@PrePersist
public void prePersist() {
createdAt = Instant.now();
}
@Data
@Entity
@Table(name = "restaurant")
public class Restaurant {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long id;
@Column(length = 100)
public String name;
@Column(length = 200)
public String address;
@Column(length = 50)
public String phone;
@Column(length = 50)
public String category;
@Column(length = 200)
public String description;
@Column(length = 10)
public Instant createdAt;
@PrePersist
public void prePersist() {
createdAt = Instant.now();
}
@OneToMany(mappedBy = "restaurant")
public List<Menu> menuList;
@OneToMany(mappedBy = "restaurant")
public List<Review> reviewList;
}
- Response:
{
"restaurant": {
"id": 1,
"name": "맛있는 식당",
"category": "한식",
"address": "서울시 강남구",
"phone": "02-1234-5678",
"description": "전통 한식집",
"avgRating": 4.5,
"reviewCount": 100,
"createdAt": "2024-12-27T10:00:00",
},
"menus": [
{
"id": 1,
"name": "김치찌개",
"price": 8000,
"description": "돼지고기 김치찌개",
"category": "찌개",
"reviewCount": 50
}
]
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MenuResponse {
public Long id;
public String name;
public Integer price;
public String description;
public String category;
public String createdAt;
}
Postman
IP로컬로도 테스트 하여 봅니다.
1.1. 음식점 목록 조회
다양한 조건으로 음식점 목록을 검색하고 조회할 수 있는 API입니다.
- URL: /api/v1/restaurants
- Method: GET
- 설명:
- 페이징 처리된 음식점 목록을 반환합니다.
- 카테고리 필터링과 키워드 검색을 지원합니다.
- 음식점의 평균 평점과 리뷰 수를 포함합니다.
- 최신 등록순으로 정렬됩니다.
- Query Parameters:
page: 페이지 번호 (기본값: 1)
size: 페이지 크기 (기본값: 10)
category: 카테고리 필터 (선택) - 한식, 중식, 일식, 양식 등
keyword: 검색어 - 이름, 주소 검색 (선택, 최소 2글자 이상)
Postman
intelliJ
@GetMapping("/api/v1/restaurants")
getRestaurants(@RequestParam int page,
@RequestParam int size,
@RequestParam(value = "category", required = false) String category,
@RequestParam(value = "keyword",required = false) String keyword) {
restaurantService.getRestaurants(page, size, category, keyword);
public RestaurantListResponse getRestaurants(int page, int size, String category, String keyword) {
Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));
// 레파지 토리 생성 및 페이징 처리
Page<Restaurant> restaurantPage;
조건문 사용시 반복을 구문 줄이는 방법
1. 예시 구문
Page <restaurantPage> restaurantPage의 반복
if (category == null && keyword == null) {
Page<Restaurant> restaurantPage =
restaurantRepository.findByCategoryAndKeyword(category, keyword, pageable);
//2. 키워드만 있는 경우 (키워드로 필터링)
} else if (category != null && keyword == null) {
Page<Restaurant> restaurantPage =
restaurantRepository.findByKeyword(keyword, pageable);
//3. 카테고리만 있는 경우 (카테고리로 필터링)
} else if (category == null && keyword != null) {
Page<Restaurant> restaurantPage =
2. 수정 구문
Page <restaurantPage> restaurantPage; // 또는 Page restaurantPage = null ; 로도 가능
if (category == null && keyword == null) {
restaurantPage =
restaurantRepository.findByCategoryAndKeyword(category, keyword, pageable);
//2. 키워드만 있는 경우 (키워드로 필터링)
} else if (category != null && keyword == null) {
restaurantPage =
restaurantRepository.findByKeyword(keyword, pageable);
//3. 카테고리만 있는 경우 (카테고리로 필터링)
} else if (category == null && keyword != null) {
restaurantPage =
위와 같이 보다 효율적으로 구문 작성이 가능합니다.
- Response:
{
"content": [
{
"id": 1,
"name": "맛있는 식당",
"category": "한식",
"address": "서울시 강남구",
"phone": "02-1234-5678",
"description": "전통 한식집",
"avgRating": 4.5,
"reviewCount": 100,
"createdAt": "2024-12-27T10:00:00"
}
],
"pageable": {
"page": 1,
"size": 10,
"totalElements": 100,
"totalPages": 10
}
}
RestaurantResponse 클래스의 경우 상세 조회 시 사용한 클래스 사용가능 합니다.
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageableResponse {
public Integer page;
public Integer size;
public Long totalElements;
public Integer totalPages;
}
public class RestaurantListResponse {
public List<RestaurantResponse> content;
public PageableResponse pageable;
}
public RestaurantListResponse getRestaurants(int page,
int size, String category, String keyword) {
PageRequest pageRequest = PageRequest.of(page - 1, size);
// 레파지 토리 생성 및 페이징 처리
Page<Restaurant> restaurantPage;
// 조건에 따라 검색
//1. 카테고리와 키워드가 모드 있는 경우 (카테고리와 키워드로 필터링)
if (category != null && keyword != null) {
restaurantPage =
restaurantRepository.findByCategoryAndKeyword(category, keyword, pageRequest);
//restaurantPage =
restaurantRepository.findByCategoryAndKeyword(category, keyword, pageable);
//2. 카테고리만 있는 경우 (카테고리로 필터링)
} else if (category != null&& keyword == null) {
restaurantPage =
restaurantRepository.findByCategory(category, pageRequest);
//3. 키워드만 있는 경우 (키워드로 필터링)
} else if ( category == null && keyword != null ) {
// restaurantPage =
restaurantRepository.findByNameContainingOrAddressContaining(category, pageable);
//위와래 같이 적용가능합니다. 하지만, 아래와 같이 적용하는 것이 더 직관적입니다.
restaurantPage = restaurantRepository.findByKeyword(keyword, pageRequest);
//4. 카테고리가 없는 경우
} else {
restaurantPage = restaurantRepository.findAll(pageRequest);
}
// entity 를 dto 로 변환
ArrayList<RestaurantResponse> restaurantResponseArrayList =
new ArrayList<>();
@GetMapping("/api/v1/restaurants")
public ResponseEntity<RestaurantListResponse> getRestaurants(@RequestParam("page") int page,
@RequestParam("size") int size,
@RequestParam(value = "category", required = false) String category,
@RequestParam(value = "keyword", required = false) String keyword){
try {
RestaurantListResponse ListResponse =
restaurantService.getRestaurants(page, size, category, keyword);
return ResponseEntity.status(200).body(ListResponse);
} catch (Exception e) {
return ResponseEntity.status(400).build();
}
}
Postman
if (category != null && keyword != null)
else if (category != null&& keyword == null)
else if ( category == null && keyword != null )
else
'API > 실습' 카테고리의 다른 글
81. [JAVA] API 문서 문제 : JDBC -> JPA 진행 (3) (1) | 2025.01.16 |
---|---|
76. [JAVA] API 문서 문제 : JDBC -> JPA 진행 (1) (0) | 2025.01.14 |
69. [ JAVA ] 공공데이터 포털 API 이용 : 영화 박스오피스순위 예시 (0) | 2025.01.13 |
63. [ JAVA ] Spring Boot를 이용한 API 통신 : 유튜브 검색 예시 (1) | 2025.01.12 |
61. [ JAVA ] API 리뷰 작성시 사진 추가 업로드 구현 (0) | 2025.01.12 |