[인프런 워밍업 클럽 1기 BE] 과제6. Layered Architecture

none_null·2024년 5월 13일
0

Java

목록 보기
7/10
post-thumbnail

문제1. Solution

FruitController

package com.group.libraryapp.controller.fruit;

import com.group.libraryapp.dto.fruit.request.FruitCreateRequest;
import com.group.libraryapp.dto.fruit.request.FruitUpdateRequest;
import com.group.libraryapp.dto.fruit.response.FruitResponse;
import com.group.libraryapp.service.fruit.FruitService;
import org.springframework.web.bind.annotation.*;

@RestController
public class FruitController {

    private final FruitService fruitService;

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

    @PostMapping("/api/v1/friut")
    public void saveFruit(@RequestBody FruitCreateRequest request){
        fruitService.saveFruit(request);
    }

    @PutMapping("/api/v1/friut")
    public void updateFruit(@RequestBody FruitUpdateRequest request){
        fruitService.updateFruit(request);
    }

    @GetMapping("/api/v1/friut/stat")
    public FruitResponse statFruit(@RequestParam String name){
        return fruitService.statFruit(name);
    }
}

FruitService

package com.group.libraryapp.service.fruit;

import com.group.libraryapp.dto.fruit.request.FruitCreateRequest;
import com.group.libraryapp.dto.fruit.request.FruitUpdateRequest;
import com.group.libraryapp.dto.fruit.response.FruitResponse;
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 void saveFruit(FruitCreateRequest request){
        fruitRepository.saveFruits(request.getName(), request.getWarehousingDate(), request.getPrice());
    }

    public void updateFruit(FruitUpdateRequest request){
        if (fruitRepository.isFruitNotExist(request.getId())) {
            throw new IllegalArgumentException("Fruit with id " + request.getId() + " does not exist");
        }
    }

    public FruitResponse statFruit(String name){
        if (fruitRepository.isFruitNotExist(name)) {
            throw new IllegalArgumentException("Fruit with name " + name + " does not exist");
        }
        return fruitRepository.statFruit(name);
    }
}

FruitRepository

package com.group.libraryapp.repository.fruit;

import com.group.libraryapp.dto.fruit.response.FruitResponse;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;

@Repository
public class FruitRepository {
    private final JdbcTemplate jdbcTemplate;

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

    public void saveFruits(String name, LocalDate warehousingDate,long price) {
        String sql = "INSERT INTO fruits (name, warehousingDate, price) VALUES (?, ?, ?)";
        jdbcTemplate.update(sql,name,warehousingDate,price);
    }

    public boolean isFruitNotExist(long id) {
        String readSql = "SELECT * FROM fruits WHERE id = ?";
        return jdbcTemplate.query(readSql, (rs, rowNum) -> 0, id).isEmpty();
    }

    public void updateFruits(long fruitId) {
        String sql = "UPDATE fruits SET isSold = 1 WHERE id = ?";
        jdbcTemplate.update(sql,fruitId);
    }

    public boolean isFruitNotExist(String name) {
        String readSql = "SELECT * FROM user WHERE name = ?";
        return jdbcTemplate.query(readSql, (rs, rowNum) -> 0, name).isEmpty();
    }

    public FruitResponse statFruit(String name) {
        String salesSql = "SELECT sum(price) FROM fruits WHERE isSold = true GROUP BY name HAVING name = ?";
        String notSalesSql = "SELECT sum(price) FROM fruits WHERE isSold = false GROUP BY name HAVING name = ?";

        long salesAmount = jdbcTemplate.queryForObject(salesSql, Long.class, name);
        long notSalesAmount = jdbcTemplate.queryForObject(notSalesSql, Long.class, name);

        return new FruitResponse(salesAmount,notSalesAmount);
    }
}

문제2. Solution

=> repository 분리하기

interface를 활용한다!!

FruitRepository

public interface FruitRepository {

    void saveFruit(String name, LocalDate warehousingDate, long price);
    void updateFruit(long id);
    FruitAmountResponse statFruit(String name);
    boolean isFruitNotExist(long id);
    boolean isFruitNotExist(String name);
}

FruitMemoryRepository

@Primary 
@Repository
public class FruitMemoryRepository implements FruitRepository {

    private final JdbcTemplate jdbcTemplate;

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

    @Override
    public void saveFruit(String name, LocalDate warehousingDate, long price) {
        String sql = "INSERT INTO fruit (name, warehousingDate, price) VALUES (?, ?, ?)";
        jdbcTemplate.update(sql, name, warehousingDate, price);
    }

    @Override
    public boolean isFruitNotExist(long id) {
        String readSql = "SELECT * FROM fruit WHERE id = ?";
        return jdbcTemplate.query(readSql, (rs, rowNum) -> 0, id).isEmpty();
    }

    @Override
    public void updateFruit(long id) {
        String updateSql = "UPDATE fruit SET is_sold  = true WHERE id = ?";
        jdbcTemplate.update(updateSql, id);
    }

    @Override
    public boolean isFruitNotExist(String name) {
        String readSql = "SELECT * FROM user WHERE name = ?";
        return jdbcTemplate.query(readSql, (rs, rowNum) -> 0, name).isEmpty();

    }

    @Override
    public FruitAmountResponse statFruit(String name) {
        String salesSql = "SELECT sum(price) FROM fruit WHERE is_sold = true GROUP BY name HAVING name = ?";
        String notSalesSql = "SELECT sum(price) FROM fruit WHERE is_sold = false GROUP BY name HAVING name = ?";

        long salesAmount = jdbcTemplate.queryForObject(salesSql, long.class, name);
        long notSalesAmount = jdbcTemplate.queryForObject(notSalesSql, long.class, name);

        return new FruitAmountResponse(salesAmount, notSalesAmount);
    }
}

FruitMySqlRepository

@Repository
public class FruitMySqlRepository implements FruitRepository {
}

💡 많은 코드를 다루기 위해서는 기능 분리가 매우 중요하다!!
이런 기능 분리를 Layered Architecture 라고 한다

Controller ← Service ← Repository (DTO는 계층 간의 정보 전달 역할)

profile
초보개발자

0개의 댓글

관련 채용 정보