인프런워밍업스터디_BE_6일차_과제

오현석·2024년 2월 23일


문제 1 & 문제 2

Fruit API를 Controller, Service, Repository로 분리하고, Repository는 과일 정보를 저장할 때 MySQL DB를 사용하도록 하는 FruitMySqlRepository, 메모리를 사용하도록 하는 FruitMemoryRepository를 각각 구현하여 Service에 스프링 컨테이너를 통해 의존성이 주입되게 해야한다.

이를 구현하기 위해 두 Repository를 바꿀 수 있어야 하므로 인터페이스 FruitRepository를 만들고, 이 인터페이스를 Repository들이 오버라이딩해서 사용할 수 있도록 구현하고 @Repository를 사용하여 스프링 빈으로 등록했다. 이때, 스프링 빈으로 등록된 Repository가 2개이므로 @Qualifier를 사용하여 Service가 원하는 Repository를 의존할 수 있게 구현하였다.

Fruit
import java.time.LocalDate;

public class Fruit {
   private long id;
   private String name;
   private LocalDate warehousingDate;
   private long price;
   private boolean sell;

   public Fruit(long id, String name, LocalDate warehousingDate, long price) {
       this.id = id;
       this.name = name;
       this.warehousingDate = warehousingDate;
       this.price = price;
   }

   public long getId() {
       return id;
   }

   public String getName() {
       return name;
   }

   public long getPrice() {
       return price;
   }

   public boolean isSell() {
       return sell;
   }

   public void setSell(boolean sell) {
       this.sell = sell;
   }
}
FruitController
@RestController
public class FruitController {
   private final FruitService fruitService;

   public FruitController(FruitService fruitService) {
       this.fruitService = fruitService;
   }

   @PostMapping("/api/v1/fruit")
   public void saveFruit(@RequestBody FruitRequest request){
       fruitService.saveFruit(request);
   }

   @GetMapping("api/v1/fruit/stat")
   public FruitResponse getFruitTotalPrice(@RequestParam String name){
       return fruitService.getFruit(name);
   }

   @PutMapping("api/v1/fruit")
   public void putFruit(@RequestBody FruitUpdateRequest request){
       fruitService.putFruit(request.getId());
   }
}
FruitService
@Service
public class FruitService{
   private final FruitRepository fruitRepository;

   public FruitService(@Qualifier("SQL") FruitRepository fruitRepository) {
       this.fruitRepository = fruitRepository;
   }

   public void saveFruit(FruitRequest fruitRequest){
       if (fruitRequest.getName() == null || fruitRequest.getWarehousingDate() == null || fruitRequest.getPrice() == null) {
           throw new IllegalArgumentException();
       }
       fruitRepository.saveFruit(fruitRequest);
   }

   public FruitResponse getFruit(String name){
       return fruitRepository.getFruit(name);
   }
   public void putFruit(long id){
       if(fruitRepository.isNotFruitExist(id)){
           throw new IllegalArgumentException();
       }
       fruitRepository.putFruit(id);
   }
}
FruitRepository
public interface FruitRepository {
   void saveFruit(FruitRequest fruitRequest);
   FruitResponse getFruit(String name);
   void putFruit(long id);
   boolean isNotFruitExist(long id);
}
FruitMySqlRepository
@Qualifier("SQL")
@Repository
public class FruitMySqlRepository implements FruitRepository{
   private final JdbcTemplate jdbcTemplate;

   public FruitMySqlRepository(JdbcTemplate jdbcTemplate) {
       this.jdbcTemplate = jdbcTemplate;
   }

   @Override
   public void saveFruit(FruitRequest fruitRequest) {
       String sql = "INSERT INTO warehouse (name, warehousingDate, price) VALUES (?,?,?)";
       jdbcTemplate.update(sql, fruitRequest.getName(),fruitRequest.getWarehousingDate(), fruitRequest.getPrice());

   }

   @Override
   public FruitResponse getFruit(String name) {
       String sql = "SELECT sell, SUM(price) AS TotalPrice FROM warehouse WHERE name = ? GROUP BY sell;";
       AtomicLong sellPrice = new AtomicLong();
       AtomicLong notSellPrice = new AtomicLong();

       List<Object> results = jdbcTemplate.query(sql, (rs, rowNum)->{
           boolean sell = rs.getBoolean("sell");
           if (rs.wasNull()){
               System.out.println("error");
               throw new IllegalArgumentException();
           }
           else if (sell){
               sellPrice.addAndGet(rs.getLong("TotalPrice"));
           }
           else{
               notSellPrice.addAndGet(rs.getLong("TotalPrice"));
           }
           return null;
       },name);
       if (results.isEmpty()) {
           throw new IllegalArgumentException("해당하는 이름의 과일이 없습니다.");
       }
       return new FruitResponse(sellPrice.get(), notSellPrice.get());
   }

   @Override
   public void putFruit(long id) {
       String sql = "UPDATE warehouse SET sell = true WHERE id = ?";
       jdbcTemplate.update(sql, id);
   }

   @Override
   public boolean isNotFruitExist(long id) {
       String readSql = "SELECT * FROM warehouse WHERE id = ?";
       return jdbcTemplate.query(readSql, (rs, rowNum)-> 0, id).isEmpty();
   }
}
FruitMemoryRepository
@Repository
public class FruitMemoryRepository implements FruitRepository{
   private List<Fruit> fruitList;
   private long id = 1;
   public FruitMemoryRepository(List<Fruit> fruitList) {
       this.fruitList = fruitList;
   }

   @Override
   public void saveFruit(FruitRequest fruitRequest) {
       Fruit fruit = new Fruit(id++, fruitRequest.getName(), fruitRequest.getWarehousingDate(), fruitRequest.getPrice());
       fruitList.add(fruit);
   }

   @Override
   public FruitResponse getFruit(String name){
       long sellPrice = 0, notSellPrice = 0;
       boolean checkNoFruit = false;
       for (Fruit fruit : fruitList){
           if ( fruit.getName().equals(name) ){
               if ( fruit.isSell() ){
                   sellPrice += fruit.getPrice();
               }
               else{
                   notSellPrice += fruit.getPrice();
               }
               checkNoFruit = true;
           }
       }
       if (!checkNoFruit){
           throw new IllegalArgumentException("해당하는 이름의 과일이 없습니다.");
       }
       return new FruitResponse(sellPrice, notSellPrice);
   }
   @Override
   public void putFruit(long id) {
       for ( Fruit fruit : fruitList ){
           if (fruit.getId() == id){
               fruit.setSell(true);
           }
       }
   }

   @Override
   public boolean isNotFruitExist(long id) {
       for(Fruit fruit : fruitList){
           if ( fruit.getId() == id ){
               return false;
           }
       }
       return true;
   }
}
profile
Backend Engineer(FastAPI, Spring, ...) / Prompt & Context Engineer / DevOps

0개의 댓글