public interface FruitRepositoryJPA extends JpaRepository<Fruit, Long>{
boolean existsByName(String name);
Optional<Fruit> findByIdAndIsSold(long id, IsSold isSold);
//SELECT sum(price) AS `sum` FROM fruit_info WHERE name = ? GROUP BY is_sold
@Query("SELECT sum(f.price) FROM fruit_info f WHERE f.name = ?1 GROUP BY f.isSold")
List<Long> sumPriceGroupByIsSold(String name);
}
FruitRepositoryJPA를 위와 같이 작성했다.
이전의 쿼리 중, 과일 판매 매출에 관한 쿼리는 group by와 통계함수를 사용했는데 이것은 JPA로 구현하기가 곤란해보였다.
그래서 @Query 어노테이션으로 별도의 쿼리를 정의해줬다.
@Entity(name = "fruit_info")
public class Fruit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name", nullable = false, length = 20)
private String name;
@Column(name = "warehousing_date", nullable = false)
private LocalDate warehousingDate;
@Column(name = "price", nullable = false)
private Long price;
@Column(name = "is_sold")
private IsSold isSold;
public Long getId() {
return id;
}
public String getName() {
return name;
}
public LocalDate getWarehousingDate() {
return warehousingDate;
}
public Long getPrice() {
return price;
}
public IsSold getIsSold() {
return isSold;
}
public Fruit(Long id, String name, LocalDate warehousingDate, Long price, IsSold isSold) {
this.id = id;
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
this.isSold = isSold;
}
public Fruit() {
}
public Fruit(Long id, String name, LocalDate warehousingDate, Long price) {
this.id = id;
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
this.isSold = IsSold.N;
}
public Fruit(String name, LocalDate warehousingDate, Long price) {
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
}
public void setIsSold(IsSold isSold) {
this.isSold = isSold;
}
}
@Service
public class FruitServiceV2 {
private final FruitRepositoryJPA fruitRepository;
public FruitServiceV2(FruitRepositoryJPA fruitRepository) {
this.fruitRepository = fruitRepository;
}
public void storeFruit(StoreFruitRequest request) {
fruitRepository.save(new Fruit(request.getName(), request.getWarehousingDate(), request.getPrice()));
}
public void soldFruit(SoldFruitRequest request){
Fruit fruit = fruitRepository.findByIdAndIsSold(request.getId(),IsSold.N).orElseThrow(IllegalArgumentException::new);
fruit.setIsSold(IsSold.Y);
fruitRepository.save(fruit);
}
public SalesFruitResponse salesFruit(String name) {
if(fruitRepository.existsByName(name)) throw new IllegalArgumentException();
List<Long> salesFruit = fruitRepository.sumPriceGroupByIsSold(name);
SalesFruitResponse response = new SalesFruitResponse(salesFruit.get(0), salesFruit.get(1));
return response;
}
}
강의에서 배운 대로 작성한 코드라 별도의 설명은 기술하지 않는다.
이제 실행해보자!
귤 데이터를 넣어 상태코드 200를 받았다. 정상적으로 데이터가 들어갔는지 위해 전체 조회를 확인해보았더니 문제가 생겼다.
분명 테이블 설계시, is_sold는 기본적으로 N이 들어가도록 기본값 설정을 해놓았는데 적용되지 않고 null로 들어간 것을 볼 수 있다.
이를 수정하기 위해 Fruit 엔티티를 수정해봤다.