과제 6. 코드 분리하기
10개월 전
1. 과제 4에서 만들었던 API를 분리해보자
// Controller
package com.group.libraryapp.controller.HW;
import com.group.libraryapp.dto.HW.FruitRequest;
import com.group.libraryapp.dto.HW.FruitSoldRequest;
import com.group.libraryapp.dto.HW.FruitStatResponse;
import com.group.libraryapp.service.fruit.FruitService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1/fruit")
public class FruitController {
private final FruitService fruitService;
public FruitController(FruitService fruitService) {
this.fruitService = fruitService;
}
@PostMapping
public FruitRequest addFruit(@RequestBody FruitRequest fruitRequest) {
return fruitService.addFruit(fruitRequest);
}
@PutMapping
public ResponseEntity<Void> markFruitAsSold(@RequestBody FruitSoldRequest request) {
fruitService.markFruitAsSold(request);
return ResponseEntity.ok().build();
}
@GetMapping("/stat")
public FruitStatResponse getFruitStat(@RequestParam("name") String name) {
return fruitService.getFruitStat(name);
}
}
// Service
package com.group.libraryapp.service.fruit;
import com.group.libraryapp.dto.HW.FruitRequest;
import com.group.libraryapp.dto.HW.FruitSoldRequest;
import com.group.libraryapp.dto.HW.FruitStatResponse;
import com.group.libraryapp.repository.fruit.FruitRepository;
import org.springframework.stereotype.Service;
@Service
public class FruitService {
private final FruitRepository fruitRepository;
public FruitService(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
public FruitRequest addFruit(FruitRequest fruitRequest) {
fruitRequest.setStatus("NOT_SOLD");
fruitRepository.addFruit(fruitRequest.getName(), fruitRequest.getWarehousingDateAsString(),
fruitRequest.getPrice(), fruitRequest.getStatus());
return fruitRequest;
}
public void markFruitAsSold(FruitSoldRequest request) {
fruitRepository.markFruitAsSold(request.getId());
}
public FruitStatResponse getFruitStat(String name) {
long soldAmount = Math.round(fruitRepository.getFruitStat(name, "SOLD"));
long notSoldAmount = Math.round(fruitRepository.getFruitStat(name, "NOT_SOLD"));
return new FruitStatResponse(soldAmount, notSoldAmount);
}
}
// Repository
package com.group.libraryapp.repository.fruit;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class FruitRepository {
private final JdbcTemplate jdbcTemplate;
public FruitRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void addFruit(String name, String warehousingDate, double price, String status) {
String sql = "INSERT INTO fruits (name, warehousingDate, price, status) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(sql, name, warehousingDate, price, status);
}
public void markFruitAsSold(long id) {
String sql = "UPDATE fruits SET status = 'SOLD' WHERE id = ?";
jdbcTemplate.update(sql, id);
}
public double getFruitStat(String name, String status) {
String sql = "SELECT SUM(price) as totalAmount FROM fruits WHERE name = ? AND status = ?";
return jdbcTemplate.queryForObject(sql, Double.class, name, status);
}
}
기존에 만들었던 API를 수업처럼 Controller - Service - Repository로 분리했다.
2. 문제 1에서 분리된 코드들 중 FruitRepository를 FruitMemoryRepository와 FruitMySqlRepository로 나누고 @Primary 어노테이션을 활용해보자.
package com.group.libraryapp.repository.fruit;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
@Primary
@Repository
public class FruitMemoryRepository implements FruitRepository {
@Override
public void addFruit(String name, String warehousingDate, double price, String status) {
// 메모리에 과일 추가하는 로직
}
@Override
public void markFruitAsSold(long id) {
// 메모리에서 과일 상태를 'SOLD'로 변경하는 로직
}
@Override
public double getFruitStat(String name, String status) {
// 메모리에서 특정 과일의 통계를 계산하는 로직
return 0; // 예시로 0으로 반환
}
}
package com.group.libraryapp.repository.fruit;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class FruitMySqlRepository implements FruitRepository {
private final JdbcTemplate jdbcTemplate;
public FruitMySqlRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void addFruit(String name, String warehousingDate, double price, String status) {
String sql = "INSERT INTO fruits (name, warehousingDate, price, status) VALUES (?, ?, ?, ?)";
jdbcTemplate.update(sql, name, warehousingDate, price, status);
}
@Override
public void markFruitAsSold(long id) {
String sql = "UPDATE fruits SET status = 'SOLD' WHERE id = ?";
jdbcTemplate.update(sql, id);
}
@Override
public double getFruitStat(String name, String status) {
String sql = "SELECT SUM(price) as totalAmount FROM fruits WHERE name = ? AND status = ?";
return jdbcTemplate.queryForObject(sql, Double.class, name, status);
}
}
이렇게 Memory와 Mysql 부분으로 레포지토리를 나누고 기본 프라이머리 값을 FruitMemoryRepository로 설정했다!
댓글을 작성해보세요.