[인프런 워밍업 클럽 스터디1기] 백엔드 - 7차 과제
진도표 7일차와 연결됩니다
우리는 JPA라는 개념을 배우고 유저 테이블에 JPA를 적용해 보았습니다. 몇 가지 문제를 통해 JPA를 연습해 봅시다! 🔥
문제1
JPA(Java Persistence API) 는 자바 객체를 관계형 데이터 베이스에 영속적으로 저장하고 조회할 수 있는 ORM 기술에 대한 표준 명세를 의미한다.
JPA 를 통해 SQL 쿼리를 작성하지 않고도 객체를 통해 데이터베이스를 조작할 수 있어 보수성이 향상된다.
Entity 클래스를 작성한 후 Repository 인터페이스를 생성해야하는데, JpaRepository를 상속받도록 하면, 기본적인 쿼리 추가, 조회, 수정, 삭제, findAll(), findById() 등의 메서드를 사용할 수 있다.
1) Entity 클래스 정의
@Entity
public class Fruits {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id = null;
@Column(nullable = false, length = 20 )
private String name;
@Column(nullable = false)
private LocalDate warehousingDate;
@Column(nullable = false)
private long price;
@Column(nullable = false)
private int saled;
public Fruits(){
}
public Fruits(long id, String name, LocalDate warehousingDate, long price, int saled) {
this.id = id;
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
this.saled = saled;
}
public Fruits(String name, LocalDate warehousingDate, long price, int saled) {
this.name = name;
this.warehousingDate = warehousingDate;
this.price = price;
this.saled = saled;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public LocalDate getWarehousingDate() {
return warehousingDate;
}
public long getPrice() {
return price;
}
public int getSaled(){
return saled;
}
public void setSaled(int saled) {
this.saled = saled;
}
}
JPARepository를 사용하여 액세스할 엔티티 클래스를 정의했다.
@Entity 어노테이션은 JPA를 사용해 테이블과 매핑할 클래스에 붙여주는 어노테이션이다. 이 어노테이션을 붙이면, JPA가 해당 클래스를 관리하게 된다.
@Id 어노테이션은 특정 속성을 기본키로 설정하는 어노테이션이다.
@GeneratedValue(startegy = GenerationType.IDENTITY) 은 기본키 생성을 DB에 위임한다는 것으로 위 클래스에서는 id 값이 자동 생성된다.
@Column 은 객체필드를 테이블 칼럼과 매핑한다.
2) JpaRepository 인터페이스 상속받는 인터페이스 생성
public interface FruitRepository extends JpaRepository<Fruits,Long> {
Optional<Fruits> findById(Long id);
long countByNameAndSaled(String name,int i);
long countByName(String name);
List<Fruits> findByPriceGreaterThan(long price);
List<Fruits> findByPriceLessThan(long price);
List<Fruits> findBySaled(int i);
}
문제2
특정 과일을 기준으로 지금까지 우리 가게를 거쳐갔던 과일 개수를 세고 싶습니다.
controller 클래스에서는 아래와 같이 getmapping 부분을 만들고
@GetMapping("/api/v1/fruit/count")
@Description("지금까지 거쳐간 특정 과일이름의 개수를 반환(7일차-문제2)")
public FruitCountResponse countName(@RequestParam String name){
return fruitService.countName(name);
}
service 클래스에서는
public FruitCountResponse countName(String name) {
Long result = fruitRepository.countByName(name);
return new FruitCountResponse(result);
}
위와 같이 FruitCountResponse 객체를 반환하도록 한다.
FruitCountResponse 클래스는 아래와 같이 간단하게 json 형식으로 "count" : 숫자 를 반환하도록 만들었다.
public class FruitCountResponse {
private long count;
public FruitCountResponse(long count) {
this.count = count;
}
public long getCount() {
return count;
}
}
아래와 같이 HTTP 응답 Body 예시와 같은 형식으로 나오는 것을 볼 수 있다.
문제3
아직 판매되지 않은 특정 금액 이상 혹은 특정 금액 이하의 과일 목록을 받아보고 싶습니다.
controller 클래스에서는
@GetMapping("/api/v1/fruit/list")
@Description("판매되지 않은 특정 금액 이상 혹은 특정 금액 이하의 과일 목록(7일차-문제3)")
public List<Fruits> getListFruit(@RequestParam String option, @RequestParam long price){
return fruitService.overviewFruitCondition(option,price);
}
service 클래스에서는
public List<Fruits> overviewFruitCondition(String option, long price) {
List<Fruits> list;
List<Fruits> result = new ArrayList<>();
if (option.equals("GTE"))
list = fruitRepository.findByPriceGreaterThan(price);
else if (option.equals("LTE")){
list = fruitRepository.findByPriceLessThan(price);
}else
throw new IllegalArgumentException("GTE, LTE 로 작성해주세요.");
for (Fruits e : list)
if (e.getSaled() == 1)
result.add(e);
return result;
}
위와 같이 List<Fruits> 를 반환하도록 한다.
위와 같이 조건을 만족하는 (6000 이하의 과일들) 결과를 출력한다.
회고
직접 JpaRepository를 상속받는 repository와 entity 를 만들어 실습해보니, 약간 익숙해진 것 같다.
위 과제를 하는 중간중간 오류(1,2) 가 났었는데,
1) getter of property ‘id’ threw exception
org.springframework.beans.InvalidPropertyException: Invalid property 'id' of bean class
위 오류에서는 long에서 Long으로 id 타입을 바꾸니 해결되었다.
2) Unknown column 'warehousing_date' in 'field list'
위 오류에서는 warehousing_date 라는 칼럼명을 못 찾아서 데이터를 save 할 수 없는 상황이였는데,
변수 값을 잘못 넣어서 오류가 났던 거라 바꾸니 해결되었다.
댓글을 작성해보세요.