일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- MS949
- 자바
- 김영한
- 인프런
- java.sql.SQLException
- jwt
- .decode('utf-8')
- 스파르타코딩클럽
- mysql
- ServerSelectionTimeoutError
- PUT과 PATCH
- 독서
- unmappable character for encoding MS949
- 스프링시큐리티
- Code
- 프로그래머스
- 알고리즘
- 객체지향
- 인텔리제이
- 에러해결법
- 엔터키 이벤트
- 항해99
- java
- JSESSIONID
- API
- WIL
- TIL
- HTML
- 자바스프링
- org.h2.jdbc.JdbcSQLSyntaxErrorException
- Today
- Total
고을마을 : 나의 코딩 이야기
항해99 27일차 TIL[@ManyToOne, @JoinColumn, .stream().forEach() ] 본문
항해99 27일차 TIL[@ManyToOne, @JoinColumn, .stream().forEach() ]
고을마을 2022. 6. 8. 02:222022년 6월 7일. 항해 27일차.
주특기 심화 주차이고 과제에 전념했던 날이었다.
솔직히 내 코드가 맞는 건지도 잘 모르겠지만 테스트를 돌려보면 통과된다!
다음은 과제의 일부이다.
- 음식점 정보 입력받아 등록
- 음식점 이름 (name)
- 최소주문 가격 (minOrderPrice)
- 허용값: 1,000원 ~ 100,000원 입력
- 100 원 단위로만 입력 가능 (예. 2,220원 입력 시 에러발생. 2,300원은 입력 가능)
- 허용값이 아니거나 100원 단위 입력이 아닌 경우 에러 발생시킴
- 기본 배달비 (deliveryFee)
- 허용값: 0원 ~ 10,000원 (예. 11,000원 입력 시 에러발생.)
- 500 원 단위로만 입력 가능 (예. 2,200원 입력 시 에러발생. 2,500원 입력 가능)
- 음식점 조회
- 등록된 모든 음식점 정보 조회 가능
- 등록 시 입력한 음식점 정보 (name, minOrderPrice, deliveryFee)
- DB 테이블 ID (id)
- 등록된 모든 음식점 정보 조회 가능
사실 1번 문제는 쉽게 할 수 있었다.
일단 Entity를 구상해봤다.
@AllArgsConstructor // @Builder 사용할때 필요함.
@NoArgsConstructor
@Getter
@Entity
@Builder
public class Food {
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private int price;
@ManyToOne
@JoinColumn(name = "restaurant_id")
private Restaurant restaurant;
public Food(FoodDto foodDto){
this.id = foodDto.getRestaurantId();
this.name = foodDto.getName();
this.price = foodDto.getPrice();
}
}
이를 토대로 컨트롤러, 레포지토리, 컨트롤러를 쉽게 만들어볼수 있었던 것 같다.
public Restaurant registerRestaurant(RestaurantDto restaurantDto){
Restaurant restaurant = new Restaurant(restaurantDto);
if(restaurantDto.getMinOrderPrice() < 1000
|| restaurantDto.getMinOrderPrice() > 100000){
throw new IllegalArgumentException("최소주문 허용가격이 아닙니다.(허용가격은 1,000원 ~ 100,000원)");
}
if(restaurantDto.getMinOrderPrice() % 100 != 0){
throw new IllegalArgumentException("100원 단위 입력값이 아닙니다.");
}
if(restaurantDto.getDeliveryFee() <0 || restaurantDto.getDeliveryFee() > 10000){
throw new IllegalArgumentException("기본배달비 허용 값이 아닙니다.(허용값: 0원 ~ 10,000원)");
}
if(restaurantDto.getDeliveryFee() % 500 != 0){
throw new IllegalArgumentException("500원 단위 입력값이 아닙니다.");
}
restaurantRepository.save(restaurant);
return restaurant;
}
public List<Restaurant> getRestaurantList(){
return restaurantRepository.findAll();
}
}
여기까지는 쉽게 끝낼 수 있었지만...
2번 문제의 난관이 기다리고 있었으니...
일단 Food Entity를 만들고 음식점 ID를 등록해줘야만 했다.
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
@ManyToOne
@JoinColumn(name = "restaurant_id")
private Restaurant restaurant;
처음에 Food에도 별도의 인조키를 두어야 하는지부터 꼬이기 시작했었는데,
Entity에 ID가 없으면 안되기에 넣어주게 됐고
Restaurant 여러개에 음식은 하나씩 넣어줘야 하기때문에 @ManyToOne을 넣어주게 됐다.
Restaurant id를 가지고 와야하기 때문에 @JoinColumn까지 넣어줬다.
@Transactional
public void registerFood(Long restaurantId, List<FoodDto> foodDtoList){
Restaurant restaurant = restaurantRepository.findById(restaurantId).orElseThrow(
() -> new NullPointerException("음식점 id가 존재하지 않음")
);
foodDtoList.stream().forEach(foodDto -> {
if(foodDto.getPrice() < 100 || foodDto.getPrice() > 1000000 ){
throw new IllegalArgumentException("음식 가격 범위가 아닙니다(가격 범위 : 100원 ~ 1,000,000원 입니다.)");
}
if(foodDto.getPrice() % 100 != 0){
throw new IllegalArgumentException("100원 단위 입력이 필요합니다.");
}
Optional<Food> food = foodRepository.findFoodByRestaurantAndName(restaurant, foodDto.getName());
if(food.isPresent()){
throw new IllegalArgumentException("같은 음식점 내에서는 음식 이름이 중복될 수 없습니다.");
}
foodDto.setRestaurantId(restaurantId);
foodRepository.save(foodDto.permit(restaurant));
});
위에는 서비스 부분인데. stream().forEach() 사용법이 무척이나 헷갈렸다.
foodDtoList에 있는 내용들을 하나씩 봐줘야하는데 도무지 감이 잡히지 않았고 구글링을 엄청나게 했던 것 같다.
https://coding-factory.tistory.com/574
[Java] 자바 스트림(Stream) 사용법 & 예제
스트림(Stream)이란? 스트림은 자바8부터 추가된 컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자입니다. Iterator와 비슷한 역할을 하지만 람다식으로 요소 처리
coding-factory.tistory.com
해당 태그의 블로그를 확인해 봄으로써 List<>에서의 stream(), forEach()을 이해하고 활용해볼 수 있었다.
Optional<Food> food = foodRepository.findFoodByRestaurantAndName(restaurant, foodDto.getName());
if(food.isPresent()){
throw new IllegalArgumentException("같은 음식점 내에서는 음식 이름이 중복될 수 없습니다.");
}
같은 음식점 내에서 음식 이름이 중복될 수 없음을 나타내는 IllegalArgumentException을 만들어 줘야했는데...
여기서도 난관이었던 것 같다.
중복을 어떻게 확인하면 될지 구글링해봤지만... 구글링 능력이 아직 부족한지 실패...
문득 로그인 기능을 공부하면서 중복 ID를 확인할때 사용했던 Optional<> isPresent()가 생각났다.
코드를 붙여넣고 약간의 수정을 해줬더니 정상적으로 작동...!
foodDto.setRestaurantId(restaurantId);
foodRepository.save(foodDto.permit(restaurant));
.permit()은
public Food permit(Restaurant restaurant){
return Food.builder()
.restaurant(restaurant)
.name(this.name)
.price(this.price)
.build();
FoodDto에 있던 함수였는데... 여기에 bulilder()가 포함되어 있다.
builder()를 통해서, restaurant의 ID, name, price를 넣고, 객체를 만들어주고, save 한 것!
테스트도 잘 통과됐다ㅠㅠ
'항해99 7기 > TIL(Today I Learned)' 카테고리의 다른 글
항해99 39일차 TIL[자기반성의 시간] (0) | 2022.06.17 |
---|---|
항해99 38일차 TIL[CORS, JSESSIONID] (0) | 2022.06.16 |
API란? (0) | 2022.06.04 |
항해99 24일차 TIL[@Transactional, 페이징 및 정렬 설계] (0) | 2022.06.04 |
항해99 23일차 TIL[자기반성의 시간] (0) | 2022.06.03 |