[인프런 워밍업 클럽 1기] BE 6일차 과제
6개월 전
문제 1
과제 #4에서 만들었던 API를 Controller - Service - Repository로 분리하기
4일차 과제 내용: https://www.inflearn.com/blogs/6676
Controller
@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;
}
댓글을 작성해보세요.