728x90
반응형
공통
spring:
datasource:
url: "jdbc:mysql://localhost/library"
username: "root"
password: ""
driver-class-NAME: com.mysql.cj.jdbc.Driver
- 기존의 application.yml 파일 활용
- library 라는 database에 fruit 테이블 생성
create table fruit (
id bigint auto_increment,
name VARCHAR(25),
warehousingDate DATE,
price long,
status VARCHAR(20),
primary key (id)
);
- id: '과일 판매'라는 이벤트가 발생할 때 백엔드가 받는 값은 id이다. 따라서 id를 컬럼을 추가했다. id는 과일 고유 번호이므로 auto_increment와 primary key 설정을 한다.
- name: String 타입
- warehousingDate: "2024-03-12"타입의 데이터를 받으므로 DATE 타입
- price: long 타입
- 왜 int를 사용하지 않고 long 타입을 사용하였는가?
- status: 과일의 판매 상태 기록
- SELL - 판매 / NOT SELL - 미판매
- fruit 테이블에 작성한 이유: 문제 2번에서 과일이 판매 발생하면 id가 넘어오면서 기록해야한다. 원래 history table을 하나 더 작성해서 기록한 후에 join을 하는 것이 적절해 보인다.
- 하지만 과제 요구사항은 과일이 판매될 때 사용해야하는 HTTP Method는 PUT이다. PUT은 수정을 의미하므로 history table에 기록을 생성하는 것과는 맞지 않다.
- 따라서 방법은 2가지이다. saveFruit할 때 history table에 같이 기록을 한다. 또는 fruit table에 status를 기록한다. 나는 두 번째 방법을 사용한다.
private final JdbcTemplate jdbcTemplate;
public ThirdAssignmentController(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
- DB를 사용하기 위해서 JdbcTemplate 가져오고 ThirdAssignmentController에 jdbcTemplate를 파라매터로 받는 기본 생성자 생성
1. 문제 1번
@PostMapping("/api/v1/fruit")
public void saveFruit(@RequestBody FruitCreateRequest request) {
String sql = "insert into fruit (name, warehousingDate, price, status) values (?, ?, ?, ?)";
jdbcTemplate.update(sql, request.getName(), request.getWarehosuingDate(), request.getPrice(), "NOT SELL");
}
- HTTP Method: POST
- PATH: /api/v1/fruit
- SQL: insert into fruit (name, warehousingData, price, status) values (?, ?, ?, ?)
- JdbcTemplate - update: SQL연산을 통해 DB갱신할 때(INSERT, DELETE, UPDATE) 사용하는 메서드
- DTO - FruitCreateRequest 생성 - name. warehousingDate, price를 가진 객체
- status - 'NOT SELL'
2. 문제 2번
@PutMapping("/api/v1/fruit")
public void updateFruit(@RequestBody FruitUpdateRequest request) {
String sql = "update fruit set status=? where id=?";
jdbcTemplate.update(sql, request.getStatus(), request.getId());
}
- HTTP Method: PUT
- HTTP Path: /api/v1/fruit
- SQL: update fruit set status=? where id=?
- 판매된 과일의 id를 통해서 status 업데이트
- JdbcTemplate - update: SQL연산을 통해 DB갱신할 때(INSERT, DELETE, UPDATE) 사용하는 메서드
- DTO - FruitUpdateRequest - id와 Status를 가진 객체
3. 문제 3번
@GetMapping("api/v1/fruit/stat")
public SalesAmountResponse getSalesAndNonSalesAmount(@RequestParam String name) {
String readSql = "select status, sum(price) as PRICE from fruit where name=? group by status";
List<StatusAndAmountResponse> result = jdbcTemplate.query(readSql, new Object[]{name}, new RowMapper<StatusAndAmountResponse>() {
@Override
public StatusAndAmountResponse mapRow(ResultSet rs, int rowNum) throws SQLException {
String status = rs.getString("status");
long price = rs.getLong("PRICE");
return new StatusAndAmountResponse(status, price);
}
});
Map<String, Long> salesAmount = new HashMap<>();
for (StatusAndAmountResponse response : result) {
salesAmount.put(response.getStatus(), response.getAmount());
}
SalesAmountResponse response = new SalesAmountResponse(salesAmount.getOrDefault("SELL", 0L), salesAmount.getOrDefault("NOT SELL", 0L));
return response;
}
- HTTP Method: GET
- GET이므로 qurey로 요청
- DTO 생성 대신 @RequestParam 으로 요청 : name 만 받으므로 DTO 생성까지 할 필요는 없어보인다.
- HTTP Path: api/v1/fruit/stat
- SQL: select status, sum(price) as PRICE from fruit where name=? group by status
- 해석: status로 group by를 한 후에 sum을 통해서 각 상태(SELL, NOT SELL)의 price를 sum한다.
- ★JdbcTemplate - query - SELECT 시 여러 row를 처리할 수 있는 메서드
- 한 개의 row 씩 처리한 후에 List에 담는다.
- 한 개의 row 처리 → 결과(status, price)→ new StatusAndAmountResponse(status, price) DTO 생성
- List<StatusAndAmountResponse> result라는 리스트에 DTO들이 들어간다!
- 여기서는 status가 SELL, NOT SELL 이므로 row 2개다. 따라서 result에는 2개의 객체 존재
- 결론: RowMapper에서 만들어진 StatusAndAmountResponse 객체는 JdbcTemplate에 의해서 List에 추가되며 작업을 모두 마치면 모든 row를 처리한 결과가 담긴 List<StatusAndAmountResponse> result가 생성된다.
- HTTP Response Body의 예시처럼 만들어야 한다.
- 현재 result 안에 StatusAndAmountResponse 객체는 status필드와 amount필드로 존재한다.
- 우리가 필요한건 SELL과 NOT SELL의 amount 한 번에 조회해야한다.
- 이를 위해서 SalesAmount DTO 객체 생성 - salesAmount필드와 noSalesAmount를 가지고 있다.
- result를 For문을 돌려 Map 콜렉션 생성 - key(sell) - value(amount)로 구성
- SELL - salesAmount필드
- NOT SELL - nonSalesAmount필드
728x90
반응형
'스터디 > 인프런' 카테고리의 다른 글
[인프런 워밍업 스터디 클럽 0기- BE] 4일차 강의 내용 정리(Section2) (0) | 2024.02.22 |
---|---|
[인프런 워밍업 스터디 클럽 0기- BE] 2일차 과제 (0) | 2024.02.20 |
[인프런 워밍업 스터디 클럽 0기- BE] 3일차 강의 내용 정리(Section2) (0) | 2024.02.20 |
[인프런 워밍업 스터디 클럽 0기- BE] 2일차 강의 내용 정리 (0) | 2024.02.20 |
[인프런 워밍업 스터디 클럽 0기- BE] 1일차 과제 (0) | 2024.02.19 |