[인프런 워밍업 클럽 0기] BE 6일차 과제
9개월 전
4일차 (https://www.inflearn.com/blogs/6687)에서 이미 애플리케이션을 계층별로 나눠서 개발했기에 여기선 복습하는 느낌으로 정리하겠습니다.
[컨트롤러]
@RestController
public class FruitController {
private final FruitService fruitService;
public FruitController(FruitService fruitService) {
this.fruitService = fruitService;
}
@PostMapping("/api/v1/fruit")
public void saveFruit(@RequestBody FruitCreateRequest request) {
fruitService.saveFruit(request);
}
@PutMapping("/api/v1/fruit")
public void updateFruitStock(@RequestBody FruitStockUpdateRequest request) {
fruitService.updateFruitStock(request);
}
@GetMapping("/api/v1/fruit/stat")
public FruitSalesRecordResponse getFruitSalesRecord(@RequestParam(value="name") String name) {
return fruitService.getFruitSalesRecord(name);
}
}
[서비스]
@Service
public class FruitService {
private final FruitRepository fruitRepository;
public FruitService(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
public void saveFruit(FruitCreateRequest request) {
fruitRepository.save(request.getName(), request.getWarehousingDate(), request.getPrice());
}
public void updateFruitStock(FruitStockUpdateRequest request) {
if (fruitRepository.isFruitEmpty(request.getId())) {
throw new IllegalStateException("등록되지 않은 과일입니다.");
}
fruitRepository.updateStock(request.getId());
}
public void getFruitSalesRecord(String name) {
if (fruitRepository.isFruitEmpty(name)) {
throw new IllegalStateException("등록되지 않은 과일입니다.");
}
return fruitRepository.getSalesRecord(name);
}
}
[레포지토리]
public interface FruitRepository {
void save(String name, LocalDate warehousingDate, Long price);
void updateStock(Long id);
FruitSalesRecordResponse getSalesRecord(String name);
boolean isFruitEmpty(Long id);
boolean isFruitEmpty(String name);
}
@Repository
public class FruitMySqlRepository implements FruitRepository {
private final JdbcTemplate jdbcTemplate;
public FruitMySqlRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void save(String name, LocalDate warehousingDate, Long price) {
String sql = "insert into fruit (name, warehousing_date, price) values (?, ?, ?)";
jdbcTemplate.update(sql, name, warehousingDate, price);
}
@Override
public void updateStock(Long id) {
String sql = "update fruit set is_sold = 1 where id = ?";
jdbcTemplate.update(sql, id);
}
@Override
public FruitSalesRecordResponse getSalesRecord(String name) {
String sql = "select is_sold, sum(price) as total_price from fruit where name = ? group by is_sold";
FruitSalesRecordResponse response = new FruitSalesRecordResponse();
jdbcTemplate.query(sql, (rs, rowNum) -> {
if (rs.getBoolean("is_sold")) {
response.setSalesAmount(rs.getLong("total_price"));
} else {
response.setNotSalesAmount(rs.getLong("total_price"));
}
return 0;
});
return response;
}
@Override
public boolean isFruitEmpty(Long id) {
String sql = "select * from fruit where id = ?";
return jdbcTemplate.query(sql, (rs, rowNum) -> 0, id).isEmpty();
}
@Override
public boolean isFruitEmpty(String name) {
String sql = "select * from fruit where name = ?";
return jdbcTemplate.query(sql, (rs, rowNum) -> 0, name).isEmpty();
}
}
@Repository
public class FruitMemoryRepository implements FruitRepository {
@Override
public void save(String name, LocalDate warehousingDate, Long price) {
}
@Override
public FruitSalesRecordResponse getSalesRecord(String name) {
return null;
}
@Override
public void updateStock(Long id) {
}
@Override
public boolean isFruitEmpty(Long id) {
return false;
}
@Override
public boolean isFruitEmpty(String name) {
return false;
}
}
메모리 DB를 이용하는 레포지토리를 추가로 생성하고 @Repository
를 선언했습니다. 이 상태에서 애플리케이션을 시행하면 에러가 발생합니다. 서비스의 fruitRepository 필드에는 fruitMySqlRepository 빈과 fruitMemoryRepository 빈 모두 들어갈 수 있다 보니 스프링 부트가 결정을 내리지 못하기 때문입니다.
@Repository
@Primary
public class FruitMySqlRepository implements FruitRepository {
// 생략
}
이럴 땐 @Primary
를 선언해 본인이 사용할 레포지토리한테 등록 우선권을 주면 됩니다.
댓글을 작성해보세요.