ㄴㅏ랏말ㅆ.ㅁㅣ

4일차 유저API와 삭제API

  • 유저 업데이트API, 삭제API 개발과 테스트
  • 예외 처리하기

사용자 이름 업데이트

HTTP method : `POST`
HTTP path : /user

HTTP 요청 Body
{
  "id": Long,
  "name" : String
}
결과 반환 X(응답 200이면 OK)

사용자 이름 삭제

HTTP method : `DELETE`
HTTP path : /user
쿼리사용 
  문자열 name(삭제되어야 하는 내용)
결과 반환 X(응답 200이면 OK)
@PutMapping("/user")
public void updateUser(@RequestBody UserUpdateRequest request) {
String sql = "UPDATE user Set name = ? WHERE id = ?";
// 유저의 정보중 해당하는 아이디를 ? 이름으로 바꾼다
jdbcTemplate.update(sql, request.getName(), request.getId());
}

@DeleteMapping("/user")
 public void deleteUser(@RequestParam String name) {
     String sql = "DELETE FROM user WHERE name = ?";
     jdbcTemplate.update(sql, name);
 }

이렇게 했을때 문제는 존재하지 않는 유저를 수정하거나 삭제해도 성공으로 200을 전달한다.


API에서 예외 던지기

그냥 throw Exception()을 던지게 되면 500번데 에러로 서버내부에 문제가 있어서 요청을 실패했다 보내준다

그래서 API에서 데이터 존재 여부를 확인해서 예외를 던져야 한다

id를 기준으로 유저가 존재하는지 확인하기 위해 select 쿼리를 작성하고 db에서 확인한다

     String readSql(확인sql) = "SELECT * FROM user WEHRE id = ?";

     jdbcTemplate.query(readSql, (rs, rowNum) -> 0, request.getId())

     readSql에 있던 ? 자리에 request.getId()가 들어가고 
     select sql의 결과가 있다면 0으로 변환된다 (rs, rowNum) -> 0
     .query는 반환된값을 List로 감싸준 형태가 되어진다

db확인 쿼리를 통해 데이터가 존재하는지 확인한다

@PutMapping("/user")
    public void updateUser(@RequestBody UserUpdateRequest request) {
        String readSql = "SELECT * FROM user WHERE id = ?";
        boolean isUserNoExist = jdbcTemplate.query(readSql, (rs, rowNum) -> 0, request.getId()).isEmpty();
        // 전체가 리스트인데, 결과가 하나라도 있으면 0이 들어있는 리스트가 나옴

        if (isUserNoExist)
            throw new IllegalArgumentException();

        String sql = "UPDATE user Set name = ? WHERE id = ?";
        // 유저의 정보중 해당하는 아이디를 ? 이름으로 바꾼다
        jdbcTemplate.update(sql, request.getName(), request.getId());
    }

    @DeleteMapping("/user")
    public void deleteUser(@RequestParam String name) {
        String readSql = "SELECT * FROM user WHERE id = ?";
        boolean isUserNoExist = jdbcTemplate.query(readSql, (rs, rowNum) -> 0, name).isEmpty();

        if (isUserNoExist)
            throw new IllegalArgumentException();

        String sql = "DELETE FROM user WHERE name = ?";
        jdbcTemplate.update(sql, name);
    }
// 이렇게 했을때 문제는 존재하지 않는 유저를 수정하거나 삭제해도 성공으로 200을 전달한다.

문제

  1. 작은 과일 가게를 운영하고 있습니다. 과일 가게에 입고된 "과일 정보"를 저장하는 API를 만들어 봅시다응답 성공시 200

    HTTP method : `POST`
    HTTP path : /api/v1/fruit 
    HTTP 요청 Body 
    { 
        "name": String, 
        "warehousingDate" : LocalDate, 
        "price": long 
    }
@RestController
@RequestMapping("/api/v1")
public class FruitController {

      @PostMapping("/fruit")
      public FruitResponse fruitInfo(@RequestBody FruitRequest request) {
          return new FruitResponse(request.getName(), request.getWarehousingDate(), request.getPrice());
      }
}
public class FruitRequest {

   private long id;
   private String name;
   private LocalDate warehousingDate;
   private long price;

   public long getId() {
      return id;
   }

   public String getName() {
      return name;
   }

   public LocalDate getWarehousingDate() {
      return warehousingDate;
   }

   public long getPrice() {
      return price;
   }
}
public class FruitResponse {

      private String name;
      private LocalDate warehousingDate;
      private long price;

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

      public String getName() {
          return name;
      }

      public LocalDate getWarehousingDate() {
          return warehousingDate;
      }

      public long getPrice() {
          return price;
      }
  }
  1. 자바에서 정수를 다루는 가장 대표적인 두 가지 방법은 intlong입니다. 이 두가지 방법 중 위 API에서 long을 사용한 이유는?
    데이터가 가격이어서 오버플로우 방지와 값의 크기를 생각해 long을 써야 한다
  2. 과일이 팔리게 되면, 우리 시스템에 팔린 과일 정보를 기록해야 합니다
    HTTP method : PUT HTTP path : /api/v1/fruit HTTP 요청 Body { "id": long }
@RestController
@RequestMapping("/api/v1")
public class FruitController {

    private final JdbcTemplate jdbcTemplate;

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

    @PutMapping("/fruit")
    public void updateFruit(@RequestBody FruitRequest request) {
        String readSql = "SELECT sold_quantity FROM fruit WHERE id = ?";
        List<Long> result = jdbcTemplate.query(readSql, (rs, rowNum) -> {
            return rs.getLong("sold_quantity");
        }, request.getId());

        String sql = "UPDATE fruit SET sold_quantity = ? WHERE id = ?";
        jdbcTemplate.update(sql, result.get(0) + 1 ,request.getId());
    }
}
  1. 특정 과일을 기준으로 팔린 금액, 팔리지 않은 금액을 조회하고 싶을때

    `(1, 사과, 3000원, 판매 O)
    (2, 사과, 4000원, 판매 X)
    (3, 사과, 3000원, 판매 O)

    이럴때 API는 판매된 금액 : 6000원, 판매되지 않은 금액 4000원이라 응답해야 할때

    HTTP method : GET 
    HTTP path : /api/v1/fruit/stat 
    HTTP query 
        name : 과일 이름 

    HTTP 응답 Body

    { 
        "salesAmount": long, 
        "notSalesAmount": long 
    }`
@RestController
@RequestMapping("/api/v1")
public class FruitController {

    private final JdbcTemplate jdbcTemplate;

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

    @GetMapping("/fruit/stat")
    public FruitStatResponse getFruitStat(@RequestParam String name) {

        String soldSql = "SELECT SUM(price) AS salesAmount FROM fruit WHERE sold_quantity > 0 AND name = ?";
        String notSoldSql = "SELECT SUM(price) AS notSalesAmount FROM fruit WHERE sold_quantity = 0 AND name = ?";

        Long salesAmount = jdbcTemplate.queryForObject(soldSql, (rs, rowNum) -> rs.getLong("salesAmount"), name);
        Long notSalesAmount = jdbcTemplate.queryForObject(notSoldSql, (rs, rowNum) -> rs.getLong("notSalesAmount"), name);

        return new FruitStatResponse(salesAmount, notSalesAmount);
    }
}
  public class FruitStatResponse {

      private final long salesAmount;
      private final long notSalesAmount;

      public FruitStatResponse(long salesAmount, long notSalesAmount) {
          this.salesAmount = salesAmount;
          this.notSalesAmount = notSalesAmount;
      }

      public long getSalesAmount() {
          return salesAmount;
      }

      public long getNotSalesAmount() {
          return notSalesAmount;
      }
  }

출처

profile

ㄴㅏ랏말ㅆ.ㅁㅣ

@동여우

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그