About Me/인프런 워밍업 클럽

[인프런 워밍업 클럽 1기] BE 4일차 과제

블로그 주인장 2024. 5. 7.

BE 4일차 과제

인프런 워밍업 클럽 1기 BE 4일차 과제인 GET API와 POST API에 대한 문제를 구현해보겠습니다

아래의 문제들을 간단하게 풀기 위해서 Controller Layer에서 코드를 구현하는것으로 하겠습니다.

즉, JPA가 아닌 JDBCTemplate를 활용하여 로직을 구현해보겠습니다.

 

문제1

 

 

문제를 해결하기 위해서는 과일 정보를 가지고 있는 데이터베이스를 생성해야한다.

아래의 SQL문을 활용하여 테이블을 생성하겠습니다.

create table fruit
(
    id               bigint auto_increment,
    name             varchar(20),
    warehousing_date date,
    price            bigint,
    is_sold          boolean default false,
    primary key (id)
);

 

요청을 위한 Body를 생성하기 위해서 Dto 클래스를 생성하겠습니다.

public class FruitCreateRequest {

  private String name;

  private LocalDate warehousingDate;

  private Long price;

  // 생성자 및 getter 생략
}

 

코드 구현 및 결과

@PostMapping("/api/v1/fruit")
public void saveFruit(@RequestBody FruitCreateRequest request) {
  String sql = "INSERT INTO fruit (name, warehousing_date, price) VALUES (?, ?, ?)";
  jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice());
}

 

POSTMAN 응답 결과

 

MySQL 생성된 데이터 컬럼

 

  • int의 경우 4byte 크기의 정수 자료형입니다.
  • long의 경우 8byte 크기의 정수 자료형입니다.
  • 즉, 2개의 자료형은 모두 정수 타입이지만 메모리 크기의 차이로 표현할 수 있는 값의 범위가 다릅니다.
  • int < long 이기에 더 넓은 수의 범위를 다룰 수 있게 됩니다. (즉, int 형으로 인한 overflow를 방지할 수 있습니다.)

 

문제2

 

과일의 판매 정보를 기록하는 API입니다. 해당 문제를 동일하게 진행하기 위해서 테이블에 임의의 데이터를 삽입하겠습니다.

 

요청 Body를 구현하기 위한 dto 클래스를 생성하겠습니다.

public class FruitSellingRequest {
  private Long id;

  public Long getId() {
    return id;
  }
}

 

코드 구현 및 결과

@PutMapping("/api/v1/fruit")
public void sellingFruit(@RequestBody FruitSellingRequest request) {
  String readSql = "SELECT * FROM fruit WHERE id = ?";
  boolean isNotExist = jdbcTemplate.query(readSql, (rs, rowNum) -> 0, request.getId()).isEmpty();
  if (isNotExist) {
    throw new IllegalArgumentException();
  }

  String sql = "UPDATE fruit SET is_sold = true WHERE id = ?";
  jdbcTemplate.update(sql, request.getId());
}

 

위의 코드를 간략하게 설명해보겠습니다.

1. SELECT 문을 활용하여 DB를 조회합니다.

2. 데이터가 없는 경우 예외처리를 진행합니다.

3. 데이터가 있는 경우 SQL문을 활용하여 조건에 맞는 데이터의 값을 변경해줍니다.

 

 

POSTMAN 응답 결과

 

 

id가 3인 데이터의 is_sold 데이터가 1(boolean true) 이 된 것을 확인할 수 있습니다.

 

문제3

 

문제의 조건을 맞춰주기 위해서 DB의 데이터를 변경하겠습니다.

 

응답 Body를 구현하기 위한 dto 클래스를 생성하겠습니다.

public class FruitStatResponse {

  private Long salesAmount;

  private Long notSalesAmount;

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

 

 

코드 구현 및 결과

@GetMapping("/api/v1/fruit/stat")
public FruitStatResponse statFruit(@RequestParam String name) {
  String saleSql = "SELECT * FROM fruit WHERE name = ? and is_sold = true";
  List<Long> salesList = jdbcTemplate.query(
      saleSql, (rs, rowNum) -> rs.getLong("price"), name
  );

  long salesAmount = salesList.stream()
      .mapToLong(Long::longValue)
      .sum();

  String notSaleSql = "SELECT * FROM fruit WHERE name = ? and is_sold = false";
  List<Long> notSalesList = jdbcTemplate.query(
      notSaleSql, (rs, rowNum) -> rs.getLong("price"), name
  );

  long notSalesAmount = notSalesList.stream()
      .mapToLong(Long::longValue)
      .sum();

  return new FruitStatResponse(salesAmount, notSalesAmount);
}

 

위의 코드를 간략하게 설명해보겠습니다.

1. SELECT 문을 활용하여 DB를 조회합니다.

2. ResultSet에서 현재 행의 price 컬럼 값을 Long 타입으로 가져오라는 의미로

    즉, 조회된 각 행에 대해 price 컬럼의 값을 리스트에 담아 반환하여 리스트에 작성합니다.

3. 위의 리스트를 스트림을 활용해서 값의 합을 반환합니다.

4. ResultSet에서 현재 행의 price 컬럼 값을 Long 타입으로 가져오라는 의미로

    즉, 조회된 각 행에 대해 price 컬럼의 값을 리스트에 담아 반환하여 리스트에 작성합니다.

5. 위의 리스트를 스트림을 활용해서 값의 합을 반환합니다.

6. 응답 값에서 나온 salesAmount와 notSalesAmount 값을 리턴합니다.

 

 

POSTMAN 응답 결과

 

  @GetMapping("/api/v1/fruit/stat")
  public FruitStatResponse statFruit(@RequestParam String name) {

    String saleSql = "SELECT SUM(price) FROM fruit"
        + " WHERE name = ? and is_sold = true"
        + " GROUP BY name ";

    Long salesAmount = jdbcTemplate.queryForObject(saleSql, Long.class, name);

    String notSaleSql = "SELECT SUM(price) FROM fruit"
        + " WHERE name = ? and is_sold = false"
        + " GROUP BY name ";

    Long notSalesAmount = jdbcTemplate.queryForObject(notSaleSql, Long.class, name);

    return new FruitStatResponse(salesAmount, notSalesAmount);
  }

 

SUM

  • 집계 함수 중 하나입니다.
  • 특정 컬럼의 값의 합계를 계산합니다.

GROUP BY

  • 집계 함수의 결과를 특정 컬럼 기준으로 결과를 출력합니다.
  • GROUP BY의 결과를 필터링한다면 HAVING 키워드를 사용합니다.

 

Reference

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

 

 

 

본 포스트는 작성자가 공부한 내용을 바탕으로 작성한 글입니다.
잘못된 내용이 있을 시 언제든 댓글로 피드백 부탁드리겠습니다.
항상 정확한 내용을 포스팅하도록 노력하겠습니다.

반응형

댓글