인프런 워밍업 클럽

인프런 워밍업 클럽/ BE 7일차 과제 : JPA 마이그레이션

킹갓홍 2024. 5. 16. 22:19

7일차 과제

문제 1

Fruit 도메인

JPA를 사용하기 위해 Fruit도메인을 만들어서 Entity로 만들었다.

@Entity
public class Fruit {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    private long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false, name = "warehousing_date")
    private LocalDate warehousingDate;

    @Column(nullable = false)
    private long price;

    @Column(nullable = false)
    private boolean state;

    protected Fruit() {}

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public LocalDate getWarehousingDate() {
        return warehousingDate;
    }

    public long getPrice() {
        return price;
    }

    public boolean isState() {
        return state;
    }

    public Fruit(FruitRequestDTO request) {
        this.name = request.getName();
        this.warehousingDate = request.getWarehousingDate();
        this.price = request.getPrice();
        this.state = false;
    }
    public void updateFruit() {
        this.state = true;
    }
}

 

 

컨트롤러는 JPA를 사용해도 똑같이 요청과 응답의 기능을 해주기 때문에 기존의 컨트롤러를 그대로 사용한다.

 

FruitServiceV2

서비스단의 경우는 V2를 새롭게 만들어서 사용했다. 

@Service
public class FruitServiceV2 {
    private final FruitRepositoryV2 fruitRepositoryV2;
    public FruitServiceV2(FruitRepositoryV2 fruitRepositoryV2) {
        this.fruitRepositoryV2 = fruitRepositoryV2;
    }

    public void storeFruit(FruitRequestDTO request) {
        Fruit fruit = fruitRepositoryV2.save(new Fruit(request));
    }

    public void updateFruit(FruitUpdateRequestDTO request) {
        Fruit fruit = fruitRepositoryV2.findById(request.getId())
                        .orElseThrow(IllegalArgumentException::new);
        fruit.updateFruit();
    }

    public FruitAmountResponse getFruitAmount(String name) {
        int salesAmount = fruitRepositoryV2.getSalesAmountByName(name);
        int notSalesAmount = fruitRepositoryV2.getNotSalesAmountByName(name);
        return new FruitAmountResponse(salesAmount,notSalesAmount);
    }

Update문의 경우, JPA Persistence를 이용해서 내부에서 로직을 처리하도록 했다.

 

FruitRepositoryV2

리포지토리도 V2로 새롭게 인터페이스로 만들고, JpaRepository를 상속받았다.

public interface FruitRepositoryV2 extends JpaRepository<Fruit,Long> {
    @Query(value = "SELECT sum(price) FROM fruit WHERE state=1 AND name=:name", nativeQuery = true)
    int getSalesAmountByName(String name);

    @Query(value = "SELECT sum(price) FROM fruit WHERE state=0 AND name=:name", nativeQuery = true)
    int getNotSalesAmountByName(String name);
}

JpaRepository를 사용하기 어려운 쿼리문은 새롭게 추상 메서드를 만들어서 사용했다.

 


문제2

출처 : 인프런 -  자바와 스프링 부트로 생애 최초 서버 만들기

 

FruitController

    //과일 총합
    @GetMapping("/api/v1/fruit/stat")
    public FruitAmountResponse getFruitAmount(@RequestParam String name) {
        return fruitServiceV2.getFruitAmount(name);
    }

 

FruitServiceV2

    public FruitCountResponse getCountByName(String name) {
        return new FruitCountResponse(fruitRepositoryV2.getCountByName(name));
    }

 

FruitRepositoryV2

    @Query(value = "SELECT COUNT(id) FROM fruit WHERE name = :name", nativeQuery = true)
    long getCountByName(String name);


결과값


문제3

출처 : 인프런 -  자바와 스프링 부트로 생애 최초 서버 만들기

 

FruitController

    //과일 리스트
    @GetMapping("/api/v1/fruit/list")
    public List<FruitResponse> getFruitList(@RequestParam String option, long price) {
        return fruitServiceV2.getFruitList(option, price);
    }

 

FruitServiceV2

public List<FruitResponse> getFruitList(String option, long price) {
        if(option.equals("GTE")) {
            List<Fruit> list = fruitRepositoryV2.findAllByGTEPrice(price);
            List<FruitResponse> fruitList = list.stream()
                    .map(fruit -> new FruitResponse(fruit.getName(), fruit.getPrice(),fruit.getWarehousingDate()))
                    .collect(Collectors.toList());
            return fruitList;

        }
        else if(option.equals("LTE")) {
            List<Fruit> list = fruitRepositoryV2.findAllByLTEPrice(price);
            List<FruitResponse> fruitList = list.stream()
                    .map(fruit -> new FruitResponse(fruit.getName(), fruit.getPrice(),fruit.getWarehousingDate()))
                    .collect(Collectors.toList());
            return fruitList;
        }
        else {
            throw new IllegalArgumentException();
        }

    }

Option이 GTE일 경우와 LTE일 경우를 비즈니스 로직에서 처리해준다.

리포지토리에서 Fruit리스트를 받고 stream을 사용해서 FruitResponse리스트로 매핑해준다.


FruitRepositoryV2

    @Query(value = "SELECT * FROM fruit WHERE price >= :price AND state = 0", nativeQuery = true)
    List<Fruit> findAllByGTEPrice(long price);

    @Query(value = "SELECT * FROM fruit WHERE price <= :price and state = 0", nativeQuery = true)
    List<Fruit> findAllByLTEPrice(long price);

 

결과값