🌝 인프런 설 릴레이 할인 시작 🌝

과제 6. 코드 분리하기

과제 6. 코드 분리하기

1. 과제 4에서 만들었던 API를 분리해보자

// Controller

package com.group.libraryapp.controller.HW;

import com.group.libraryapp.dto.HW.FruitRequest;
import com.group.libraryapp.dto.HW.FruitSoldRequest;
import com.group.libraryapp.dto.HW.FruitStatResponse;
import com.group.libraryapp.service.fruit.FruitService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v1/fruit")
public class FruitController {

    private final FruitService fruitService;

    public FruitController(FruitService fruitService) {
        this.fruitService = fruitService;
    }

    @PostMapping
    public FruitRequest addFruit(@RequestBody FruitRequest fruitRequest) {
        return fruitService.addFruit(fruitRequest);
    }

    @PutMapping
    public ResponseEntity<Void> markFruitAsSold(@RequestBody FruitSoldRequest request) {
        fruitService.markFruitAsSold(request);
        return ResponseEntity.ok().build();
    }

    @GetMapping("/stat")
    public FruitStatResponse getFruitStat(@RequestParam("name") String name) {
        return fruitService.getFruitStat(name);
    }
}


// Service

package com.group.libraryapp.service.fruit;

import com.group.libraryapp.dto.HW.FruitRequest;
import com.group.libraryapp.dto.HW.FruitSoldRequest;
import com.group.libraryapp.dto.HW.FruitStatResponse;
import com.group.libraryapp.repository.fruit.FruitRepository;
import org.springframework.stereotype.Service;

@Service
public class FruitService {

    private final FruitRepository fruitRepository;

    public FruitService(FruitRepository fruitRepository) {
        this.fruitRepository = fruitRepository;
    }

    public FruitRequest addFruit(FruitRequest fruitRequest) {
        fruitRequest.setStatus("NOT_SOLD");
        fruitRepository.addFruit(fruitRequest.getName(), fruitRequest.getWarehousingDateAsString(),
                fruitRequest.getPrice(), fruitRequest.getStatus());
        return fruitRequest;
    }

    public void markFruitAsSold(FruitSoldRequest request) {
        fruitRepository.markFruitAsSold(request.getId());
    }

    public FruitStatResponse getFruitStat(String name) {
        long soldAmount = Math.round(fruitRepository.getFruitStat(name, "SOLD"));
        long notSoldAmount = Math.round(fruitRepository.getFruitStat(name, "NOT_SOLD"));
        return new FruitStatResponse(soldAmount, notSoldAmount);
    }
}


// Repository

package com.group.libraryapp.repository.fruit;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class FruitRepository {

    private final JdbcTemplate jdbcTemplate;

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

    public void addFruit(String name, String warehousingDate, double price, String status) {
        String sql = "INSERT INTO fruits (name, warehousingDate, price, status) VALUES (?, ?, ?, ?)";
        jdbcTemplate.update(sql, name, warehousingDate, price, status);
    }

    public void markFruitAsSold(long id) {
        String sql = "UPDATE fruits SET status = 'SOLD' WHERE id = ?";
        jdbcTemplate.update(sql, id);
    }

    public double getFruitStat(String name, String status) {
        String sql = "SELECT SUM(price) as totalAmount FROM fruits WHERE name = ? AND status = ?";
        return jdbcTemplate.queryForObject(sql, Double.class, name, status);
    }
}

기존에 만들었던 API를 수업처럼 Controller - Service - Repository로 분리했다.

2. 문제 1에서 분리된 코드들 중 FruitRepository를 FruitMemoryRepository와 FruitMySqlRepository로 나누고 @Primary 어노테이션을 활용해보자.

package com.group.libraryapp.repository.fruit;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

@Primary
@Repository
public class FruitMemoryRepository implements FruitRepository {

    @Override
    public void addFruit(String name, String warehousingDate, double price, String status) {
        // 메모리에 과일 추가하는 로직
    }

    @Override
    public void markFruitAsSold(long id) {
        // 메모리에서 과일 상태를 'SOLD'로 변경하는 로직
    }

    @Override
    public double getFruitStat(String name, String status) {
        // 메모리에서 특정 과일의 통계를 계산하는 로직
        return 0; // 예시로 0으로 반환
    }
}
package com.group.libraryapp.repository.fruit;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class FruitMySqlRepository implements FruitRepository {

    private final JdbcTemplate jdbcTemplate;

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

    @Override
    public void addFruit(String name, String warehousingDate, double price, String status) {
        String sql = "INSERT INTO fruits (name, warehousingDate, price, status) VALUES (?, ?, ?, ?)";
        jdbcTemplate.update(sql, name, warehousingDate, price, status);
    }

    @Override
    public void markFruitAsSold(long id) {
        String sql = "UPDATE fruits SET status = 'SOLD' WHERE id = ?";
        jdbcTemplate.update(sql, id);
    }

    @Override
    public double getFruitStat(String name, String status) {
        String sql = "SELECT SUM(price) as totalAmount FROM fruits WHERE name = ? AND status = ?";
        return jdbcTemplate.queryForObject(sql, Double.class, name, status);
    }
}

이렇게 Memory와 Mysql 부분으로 레포지토리를 나누고 기본 프라이머리 값을 FruitMemoryRepository로 설정했다!

댓글을 작성해보세요.

채널톡 아이콘