[인프런 워밍업 클럽 1기] BE 6일차 과제
문제 1과제 #4에서 만들었던 API를 Controller - Service - Repository로 분리하기4일차 과제 내용: https://www.inflearn.com/blogs/6676Controller@RequiredArgsConstructor @RestController @RequestMapping("/api/v1/fruit") public class FruitController { private final FruitService fruitService; @PostMapping public ResponseEntity<?> savedFruit(@RequestBody FruitRequest request) { fruitService.save(request); return ResponseEntity.ok().build(); } @PutMapping public ResponseEntity<?> FruitStateUpdate(@RequestBody FruitRequest request) { fruitService.stateUpdate(request); return ResponseEntity.ok().build(); } @GetMapping("/stat") public ResponseEntity<?> isSaleStateTotalPrice(@RequestParam String name) { return ResponseEntity.ok(fruitService.getSum(name)); } }Service@RequiredArgsConstructor @Service public class FruitService { private final FruitRepository fruitRepository; public void save(FruitRequest request) { fruitRepository.saveFruit(request); } public void stateUpdate(FruitRequest request) { boolean isFruitNotExist = fruitRepository.isFruitNotExist(request.getId()); if (isFruitNotExist) { throw new IllegalStateException("일치하는 과일 정보가 없습니다."); } fruitRepository.updateFruit(request.getId()); } public FruitTotalPriceResponse getSum(String name) { boolean isFruitNotExist = fruitRepository.isFruitNotExist(name); if (isFruitNotExist) { throw new IllegalStateException("일치하는 과일 정보가 없습니다."); } List<FruitTotalPriceResponse> sumResult = fruitRepository.getSum(name); long salesAmount = 0; long noSalesAmount = 0; for (FruitTotalPriceResponse result : sumResult) { salesAmount += result.getSalesAmount(); noSalesAmount += result.getNoSalesAmount(); } return new FruitTotalPriceResponse(salesAmount, noSalesAmount); } } Repository @RequiredArgsConstructor @Repository public class FruitRepository { private final JdbcTemplate jdbcTemplate; public void saveFruit(FruitRequest request) { String sql = "insert into fruit (name, warehousingDate, price) values (?, ? ,?)"; jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice()); } public void updateFruit(long id) { String sql = "update fruit set is_sale = 1 where id = ?"; jdbcTemplate.update(sql, id); } public List<FruitTotalPriceResponse> getSum(String name) { String sql = "select is_sale, sum(price) as totalPrice from fruit " + "where name = ? group by is_sale"; return jdbcTemplate.query(sql, new Object[]{name}, (rs, rowNum) -> new FruitTotalPriceResponse( rs.getBoolean("is_sale") ? rs.getLong("totalPrice") : 0, !rs.getBoolean("is_sale") ? rs.getLong("totalPrice") : 0)); } public boolean isFruitNotExist(long id) { String sql = "select * from fruit where id = ?"; return jdbcTemplate.query(sql, (rs, rowNum) -> 0, id).isEmpty(); } public boolean isFruitNotExist(String name) { String sql = "select * from fruit where name = ?"; return jdbcTemplate.query(sql, (rs, rowNum) -> 0, name).isEmpty(); } } 문제 2 FruitRepository를 FruitMemoryRepository 와 FruitMemoryRepository 로 나누자 먼저 FruitRepository를 만든다public interface FruitRepository { public void saveFruit(FruitRequest request); public void updateFruit(long id); public List<FruitTotalPriceResponse> getSum(String name); public boolean isFruitNotExist(long id); public boolean isFruitNotExist(String name); }FruitMemoryRepository@Primary @Repository public class FruitMemoryRepository implements FruitRepository{ private final List<FruitRequest> fruits = new ArrayList<>(); @Override public void saveFruit(FruitRequest request) { fruits.add(request); } @Override public void updateFruit(long id) { fruits.stream() .filter(fruit -> fruit.getId() == id) .findFirst() .ifPresent(fruit -> fruit.setSale(true)); } @Override public List<FruitTotalPriceResponse> getSum(String name) { return fruits.stream() .filter(fruit -> fruit.getName().equals(name)) .collect(Collectors.groupingBy(FruitRequest::isSale, Collectors.summingLong(FruitRequest::getPrice))) .entrySet().stream() .map(entry -> new FruitTotalPriceResponse( entry.getKey() ? entry.getValue() : 0, !entry.getKey() ? entry.getValue() : 0)) .collect(Collectors.toList()); } @Override public boolean isFruitNotExist(long id) { return fruits.stream().noneMatch(fruit -> fruit.getId() == id); } @Override public boolean isFruitNotExist(String name) { return fruits.stream().noneMatch(fruit -> fruit.getName().equals(name)); } } FruitMySqlRepository@Qualifier("mysql") @RequiredArgsConstructor @Repository public class FruitMySqlRepository implements FruitRepository { private final JdbcTemplate jdbcTemplate; public void saveFruit(FruitRequest request) { String sql = "insert into fruit (name, warehousingDate, price) values (?, ? ,?)"; jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice()); } public void updateFruit(long id) { String sql = "update fruit set is_sale = 1 where id = ?"; jdbcTemplate.update(sql, id); } public List<FruitTotalPriceResponse> getSum(String name) { String sql = "select is_sale, sum(price) as totalPrice from fruit " + "where name = ? group by is_sale"; return jdbcTemplate.query(sql, new Object[]{name}, (rs, rowNum) -> new FruitTotalPriceResponse( rs.getBoolean("is_sale") ? rs.getLong("totalPrice") : 0, !rs.getBoolean("is_sale") ? rs.getLong("totalPrice") : 0)); } public boolean isFruitNotExist(long id) { String sql = "select * from fruit where id = ?"; return jdbcTemplate.query(sql, (rs, rowNum) -> 0, id).isEmpty(); } public boolean isFruitNotExist(String name) { String sql = "select * from fruit where name = ?"; return jdbcTemplate.query(sql, (rs, rowNum) -> 0, name).isEmpty(); } } FruitService 부분에 생성자에 @Qualifier("mysql")가 있기 때문에 FruitMemoryRepository에 @Primary 어노테이션이 있더라도 직접 지정한 클래스가 우선순위가 높기 때문에 FruitMemoryRepository 주입 받는다. public FruitService(@Qualifier("mysql")FruitRepository fruitRepository) { this.fruitRepository = fruitRepository; }