![[인프런 워밍업 클럽 BE 0기] 7일차 과제](https://cdn.inflearn.com/public/files/blogs/5ebcd8fb-969e-49ee-acc4-e4b469e54977/image.png)
[인프런 워밍업 클럽 BE 0기] 7일차 과제
문제 1
과제 #6에서 만들었던 Fruit 기능들을 JPA를 이용하도록 변경해보세요
Fruit
@Entity
public class Fruit {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id = null;
@Column(nullable = false, length = 20, name = "name")
private String name;
private Integer price;
private boolean isSold;
private LocalDate warehousingDate;
protected Fruit() {}
public Fruit(String name, Integer price,
boolean isSold, LocalDate warehousingDate) {
if(name == null || name.isBlank()) {
throw new IllegalArgumentException(String.format("name(%s)은 존재하지 않습니다.
다시 입력해주세요.", name));
}
this.name = name;
this.price = price;
this.isSold = isSold;
this.warehousingDate = warehousingDate;
}
public void updateName(String name) {
this.name = name;
}
}
FruitRepository
public interface FruitRepository extends JpaRepository<Fruit, Long> {
Optional<Fruit> findByName(String name, boolean isSold);
}
FruitReponse
public class FruitReponse {
private String name;
private LocalDate warehousingDate;
private long price;
private boolean isSold;
private long id;
public FruitReponse(String name, LocalDate warehousingDate,
long price, boolean isSold, long id) {
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
this.isSold = isSold;
this.id = id;
}
public FruitReponse(Fruit fruit) {
this.name = getName();
this.warehousingDate = getWarehousingDate();
this.price = getPrice();
this.isSold = getSold();
this.id = getId();
}
public String getName() {
return name;
}
public LocalDate getWarehousingDate() {
return warehousingDate;
}
public long getPrice() {
return price;
}
public boolean getSold() {
return isSold;
}
public long getId() {
return id;
}
}
FruitRequest
FruitUpdateRequest
public class FruitUpdateRequest { private long id; private String name; public long getId() { return id; } public String getName() { return name; } }
FruitCreateRequest
public class FruitCreateRequest {
private String name;
private LocalDate warehousingDate;
private Integer price;
private boolean isSold;
private long id;
public long getId() {
return id;
}
public boolean getSold() {
return isSold;
}
public String getName() {
return name;
}
public LocalDate getWarehousingDate() {
return warehousingDate;
}
public int getPrice() {
return price;
}
}
FruitService
@Service
public class FruitServiceV2 {
private final FruitRepository fruitRepository;
public FruitServiceV2(FruitRepository fruitRepository) {
this.fruitRepository = fruitRepository;
}
public void saveFruit(FruitCreateRequest request) {
Fruit fruit = fruitRepository.save(new Fruit(request.getName(),request.getPrice(), request.getSold(), request.getWarehousingDate()));
}
public List<FruitReponse> getFruit() {
return fruitRepository.findAll().stream()
.map(FruitReponse::new)
.collect(Collectors.toList());
}
public void updateFruit(FruitUpdateRequest request) {
Fruit fruit = fruitRepository.findById(request.getId())
.orElseThrow(IllegalArgumentException::new);
fruit.updateName(request.getName());
fruitRepository.save(fruit);
}
}
문제 2
우리는 특정 과일을 기준으로 지금까지 우리 가게를 거쳐갔던 과일 개수를 세고 싶습니다.
<문제 1>에서 만들었던 과일 Entity Class를 이용해 기능을 만들어 보세요
예를 들어
(1, 사과, 3000원, 판매 O)
(2, 바나나, 4000원, 판매 X)
(3, 사과, 3000원, 판매 O)
와 같은 세 데이터가 있고, 사과를 기준으로 과일 개수를 센다면, 우리의 API는 2를 반환 할 것입니다.
구제적인 스펙은 다음과 같습니다.
HTTP method :
GET
HTTP path :
/api/v1/fruit/count
HTTP query
name : 과일 이름
예시
GET /api/v1/fruit/count?name=사과
HTTP 응답 Body
HTTP 응답 Body예시
FruitController
@GetMapping("/api/v1/fruit/count")
public FruitCountResponse countFruit(@RequestParam String name) {
return fruitService.countFruit(name);
}
FruitRepository
//Fruit 클래스
public void updateName(String name) {
this.name = name;
}
//FruitRepository 인터페이스
List<Fruit> findAllByName(String name);
FruitJdbcRepository
public void countFruit(boolean isSold, long id) {
String sql = "UPDATE fruit SET isSold = 1 WHERE id = ?";
jdbcTemplate.update(sql, isSold, id);
}
FruitService
FruitServiceV1
public void countFruit(FruitCreateRequest request) { fruitJdbcRepository.countFruit(request.getSold(), request.getId()); }
FruitServiceV2
public FruitCountResponse countFruit(String name) {
long count = fruitRepository.findAllByName(name).stream().count();
return new FruitCountResponse(count);
}
문제 3
우리는 아직 판매되지 않은 특정 금액 이상 혹은 특정 금액 이하의 과일 목록을 받아보고 싶습니다.
구체적인 스펙은 다음과 같습니다.
HTTP method :
GET
HTTP path :
/api/v1/fruit/list
HTTP query
option : "GTE" 혹은 "LTE" 라는 문자열이 들어온다.
GTE : greater than equal 의 의미
LTE : less than equal 의 의미
price : 기준이 되는 금액이 들어온다.
예시 1 -
GET /api/v1/fruit/list?option=GTE&price=3000
판매되지 않은 3000원 이상의 과일 목록을 반환해야 한다.
예시 2 -
GET /api/v1/fruit/list?option=LTE&price=5000
판매되지 않은 5000원 이하의 과일 목록을 반환해야 한다.
HTTP 응답 Body
HTTP 응답 Body예시
FruitController
@GetMapping("/api/v1/fruit/list") public List<FruitResponse> listFruit(@RequestParam String option, long price) { return fruitService.listFruit(option, price); }
FruitRepository
List<Fruit> findAllByPriceGreaterThanEqualAndIsSold(long price,boolean isSold);
List<Fruit> findAllByPriceLessThanEqualAndIsSold(long price,boolean isSold);
FruitServiceV2
public List<FruitResponse> listFruit(String option, long price) {
List<Fruit> fruits;
if (option.equals("GTE")) {
fruits = fruitRepository.findAllByPriceGreaterThanEqualAndIsSold(price, false);
} else if (option.equals("LTE")) {
fruits = fruitRepository.findAllByPriceLessThanEqualAndIsSold(price, false);
} else {
throw new IllegalArgumentException();
}
return fruits.stream()
.map(FruitResponse::new)
.collect(Collectors.toList());
}
댓글을 작성해보세요.