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을 전달한다.
문제
작은 과일 가게를 운영하고 있습니다. 과일 가게에 입고된 "과일 정보"를 저장하는 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;
}
}
- 자바에서 정수를 다루는 가장 대표적인 두 가지 방법은
int
와long
입니다. 이 두가지 방법 중 위 API에서long
을 사용한 이유는?데이터가 가격이어서 오버플로우 방지와 값의 크기를 생각해 long을 써야 한다
- 과일이 팔리게 되면, 우리 시스템에 팔린 과일 정보를 기록해야 합니다
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, 사과, 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;
}
}
출처
- https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html Class JdbcTemplate
- https://www.inflearn.com/course/lecture?courseSlug=%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%84%9C%EB%B2%84%EA%B0%9C%EB%B0%9C-%EC%98%AC%EC%9D%B8%EC%9B%90 14~16강
'TIL > 자바와 스프링부트로 서버까지 배포하기' 카테고리의 다른 글
인프런 워밍업 스터디 클럽 0기 BE - 1주차 발자국 (0) | 2024.02.25 |
---|---|
5일차 좋은코드와 Controller분리 (0) | 2024.02.23 |
3일차 MySQL과 데이터베이스 (0) | 2024.02.21 |
2일차 유저API와 POST API (0) | 2024.02.20 |
1일차 HTTP와 API, 서버 (0) | 2024.02.19 |