4일차 과제는 API를 직접만들어보는 과제였다.
문제1
우리는 작은 과일 가게를 운영하고있습니다. 과일 가게에 입고된 "과일 정보"를 저장하는 API를 만들어 봅시다.
API 스펙
위의 요구사항을 보고 우선 값을 저장할수있는 테이블을 생성해주고
요청값을 파라미터로 받아줄 객체를 생성했다.
테이블 생성
CREATE TABLE fruitshop (
id int PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
warehousedate DATETIME,
price INT
);
//이후 필드 추가 , 과일의 판매여부를 체크할 필드
ALTER TABLE fruitshop
ADD sell BOOLEAN DEFAULT false;
파라미터를 전달해줄 DTO객체
public class FruitSaveRequest {
private String name;
private Long price;
private String warehousingDate;
public String getName() {
return name;
}
public Long getPrice() {
return price;
}
public String getWarehousingDate() {
return warehousingDate;
}
}
아직 DAO와 DTO의 기준이 모호하다 . 해당객체는 파라미터를받아서 insert 쿼리에 넣어주기위한 용도로만 사용하므로 DTO라고 생각한다.
컨트롤러 코드
@RestController
@RequestMapping("/api/v1/fruit")
public class FruitShopController {
private final JdbcTemplate template;
public FruitShopController(JdbcTemplate template) {
this.template = template;
}
@PostMapping
public void saveFruit(@RequestBody FruitSaveRequest request){
String sql = "insert into fruitshop (name,warehousedate,price) values (?,?,?)";
template.update(sql,request.getName(),request.getWarehousingDate(),request.getPrice());
}
}
json으로 들어오는 파라미터가 FruitSaveRequest에 매칭되어서 saveFruit메서드에 파라미터로 들어가게되고
template.update 에서 sql의 파라미터로 사용된다.
*자바에서 정수를 다루는 가장 대표적인 두 가지 방법은 int 와 long 이다.
이 두가지 방법 중 위 API에서 long을 사용한 이유는 무엇일까?
값이나 id값은 int자료형으로는 커버할수있는 범위가 작기때문에 값이 얼마나 들어올지 예측할수없는 db의 경우에 커버리지를 넓게 잡기위해 long타입으로 지정해주는듯 하다.
문제2
과일이 팔리게 되면, 우리 시스템에 팔린 과일 정보를 기록해야 합니다.
API스펙
id를 파라미터로 받아서 조건에 맞는 필드를 업데이트 해주면 될것같다.
@PutMapping
public void sellFruit(@RequestBody Map<String, Object> requestJson){
long id = Long.parseLong(requestJson.get("id").toString()); //id값
String readSql = "select id from fruitshop where id = ?"; // 값이 있는지 확인하기위한 쿼리
Boolean isUserNotExist = template.query(readSql, (rs, rowNum) -> 0, id).isEmpty(); //(rs, rowNum) -> 0 결과값이 있는 경우 0을 반환
if(isUserNotExist){
throw new IllegalArgumentException("수정할 자료가 없습니다.");
}
String sql = "update fruitshop set sell = true where id = ?";
template.update(sql,id);
}
해당하는 아이디의 값이있는지 검증하고 값이 있으면 해당 값의 sell을 true로 변경해준다. (판매되었다는 의미)
여기에서는 값을 받기위해서 객체를 생성하지않고 Map을통해서 들어오는 Json을 받아서 long타입의 id로 변경해주었다.
문제3
우리는 특정 괴일을 기준으로 팔린 금액, 팔리지 않은 금액을 조회하고 싶습니다.
API스펙
@GetMapping("/stat")
public FruitShopAmoutResponse getAmount(@RequestParam String name){
String sql = "SELECT id,name,warehousedate,price,sell FROM fruitshop where name = ? ";
List<FruitShopResponse> query = template.query(sql,new Object[]{name}, (rs, rowNum) -> {
System.out.println("rs = " + rs);
long id = rs.getLong("id");
String fruitname = rs.getString("name");
String warehouseDate = rs.getString("warehouseDate");
long price = rs.getLong("price");
boolean sell = rs.getBoolean("sell");
return new FruitShopResponse(id, fruitname, warehouseDate, price, sell);
});
FruitShopAmoutResponse fruitShopAmoutResponse = getFruitShopAmoutResponse(query);
return fruitShopAmoutResponse;
}
private static FruitShopAmoutResponse getFruitShopAmoutResponse(List<FruitShopResponse> result) {
long salesAmount = result.stream()
.filter(rs -> rs.getSell())
.mapToLong(rs -> rs.getPrice())
.sum();
long notSalesAmount = result.stream()
.filter(rs -> !rs.getSell())
.mapToLong(rs -> rs.getPrice())
.sum();
FruitShopAmoutResponse response = new FruitShopAmoutResponse(salesAmount, notSalesAmount);
return response;
}
'백엔드 > 자바' 카테고리의 다른 글
[인프런 워밍업 클럽_0기] BE세번째 과제 진도표 6일 - Controller분리 (Controller,Service,Repository) (0) | 2024.02.26 |
---|---|
[인프런 워밍업 클럽_0기] BE세번째 과제 진도표 2일 - Controller (0) | 2024.02.25 |
[인프런 워밍업 클럽_0기] BE세번째 과제 진도표 1일 - 어노테이션(annotation) (0) | 2024.02.25 |
[인프런 워밍업 클럽_0기] BE네번째 과제 진도표 5일 - 클린코드 (1) | 2024.02.23 |
[인프런 워밍업 클럽_0기] BE세번째 과제 진도표 3일 - 람다(Lamda) (0) | 2024.02.21 |