본문 바로가기
공부/메모

스프링 심화과정 - 순한맛 2단계 음식조회, 중복

by 고구밍 2022. 4. 5.

2단계 음식 조회문제

더보기
  • 음식점 ID 및 음식 정보 입력받아 등록
    1. 음식점 ID (restaurantId)
      1. 음식점 DB 테이블 ID
    2. 음식명 (name)
      1. 같은 음식점 내에서는 음식 이름이 중복될 수 없음 (예. '자담치킨 강남점'에 '후라이드치킨' 이 이미 등록되어 있다면 중복하여 등록할 수 없지만, 다른 음식점인 '맘스터치 강남점'에는 '후라이드치킨' 을 등록 가능)
    3. 가격 (price)
      1. 허용값: 100원 ~ 1,000,000원
      2. 100 원 단위로만 입력 가능 (예. 2,220원 입력 시 에러발생. 2,300원 입력 가능)
      3. 허용값이 아니거나 100원 단위 입력이 아닌 경우 에러 발생시킴
  • 메뉴판 조회
    • 하나의 음식점에 등록된 모든 음식 정보 조회
      1. 등록 시 입력한 음식 정보 (name, price)
      2. DB 테이블 ID (id)

 

API 명세서

  API Path Request Body Sample Response Body Sample
음식 등록 POST /restaurant/{restaurantId}/food/register [
{
name: "쉑버거 더블"
price: 10900
},
{
name: "치즈 감자튀김"
price: 4900
},
{
name: "쉑버거 더블"
price: 5900
}

]
 
메뉴판 조회 GET /restaurant/{restaurantId}/foods   [
{
id: 1
name: "쉑버거 더블"
price: 10900
},
{
id: 2
name: "치즈 감자튀김"
price: 4900
},
{
id: 3
name: "쉑버거 더블"
price: 5900
}

]

 

POST ->

대괄호 [] : 리스트

중괄호 {} -> 3개

각각은 음식명(name)과 음식가격(price)이 있음

 

문제점

더보기

 

음식 등록 (POST)작업 후 FoodService에서 아래 음식 중복검사를 하는 코드를 넣었을 때 

 

음식 등록이 안 되는 일이 발생하였음

 

아래에는 2가지 방법으로 작성하였지만, 결과는 똑같이 발생 함

 

 

해결과정

더보기

결론부터 말하자면 FoodService에

@Transactional이라는 어노테이션을 안 넣어서 발생한 문제이다.

 

 

1. 중복검사하는 두가지 방법 중에서 2번째 문장으로 해결해 보았습니다.

 

FoodService
FoodRepository

다음과 같이 입력해 보았지만, 결과는 동일 하였습니다.

 

2. 중간의 값들을 출력해서 확인해 보자

 

우선 for each문으로 돌아가고 있는 코드에서, name과 price에 값이 잘 들어오는지 출력해 보았습니다.

 

FoodService
name과 price 값이 잘 나오는 것을 알 수 있음
Foodlist의 값도 검사해 보았을 때 값이 1로 잘 되는 것을 알 수 있었다.

 

3. 다른 문제들도 확인 해 보자

 

안 되는 부분에서의 Foodlist의 값을 확인 해 보는데, 1로 동일하게 되어있었다.

 

뭔가 위에서 검사한 중복결과가 초기화가 안되어서,

 

음식이름이 중복되어 있다는 코드에서 막히는 것으로 추측 하였다.

 

 

확인 결과 FoodService에 @Transactional 어노테이션을 넣지 않았기 때문에 발생한 문제였습니다.

 

 

 @Transactional 

  • 데이터베이스의 상태를 변경하는 작업 또는 한번에 수행되어야 하는 연산들을 의미한다.
  • begin, commit 을 자동으로 수행해준다.
  • 예외 발생 시 rollback 처리를 자동으로 수행해준다.
  • 트랜잭션은 4가지의 성질을 가지고 있다.

원자성(Atomicity) :

  • 한 트랜잭션 내에서 실행한 작업들은 하나의 단위로 처리한다. 즉, 모두 성공 또는 모두 실패.

일관성(Consistency) :

  • 트랜잭션은 일관성 있는 데이타베이스 상태를 유지한다. (data integrity 만족 등.)

격리성(Isolation) :

  • 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 격리해야한다.

영속성(Durability) : 

  • 트랜잭션을 성공적으로 마치면 결과가 항상 저장되어야 한다.

 

https://velog.io/@kdhyo/JavaTransactional-Annotation-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-26her30h

 

[Java]@Transactional Annotation 알고 쓰자

초반 @Transactional 어노테이션에 대해 자세히 알아보지 않고,막연히 롤백때 사용한다고 하여 SQL C,U,D 를 할 때마다 메소드 위에 붙여서 사용하곤 하였다.하지만, 내 코드를 보신 선임께서 단지 @Tran

velog.io

 

 

 

테스트 결과가 잘 나옵니다.

 

 

 

 

 

<추가 내용>

더보기
1. 음식점 음식메뉴 조회
 

 

어제 배운 내용데로,

 

url으로 restaurantId를 받기 때문에 showMenu으로 받는 인자 값을

@PatchVariable 이라는 이노테이션을 활용하여 받았고,

이 것을 FoodDto가 아닌, Entity인 Food의 리스트에 보내주었습니다.

 

그다음 리턴 값으로 FoodRepository에서

RestaurantId(음식점 번호)값에 해당하는 리스트를 전부 조회하도록 하였습니다.

 

 

Repository에서는 findAllByRestayrabtId를 통해서

GetMapping에서 요청한컨트롤러에서 "restaurantId"값에 해당하는 음식들을 불러왔습니다.

 

 


 

2. POST와 GET의 요청 진행과정을 어떻게 되나요?

 

우선 제가 만든 흐름은

음식점에 음식을 등록하는 과정은

POST)

컨트롤러 -> Dto -> 서비스 -> Entity -> 레파지토리 (저장)

 

이고, 음식점에서 등록된 메뉴를 조회하는 것은

GET)

컨트롤러 -> Entity -> 레파지토리 (조회) -> 컨트롤러 (return 응답)

이 있으며, 다른방법으로는 컨트롤러 -> Entity사이에 Service를 거치는 방법도 있다고 합니다.

 

 

 


 

3. 생성자의 용도 - 언제사용하는지

 

만들고나니 Dto에서 FoodDto와 RestaurantDto에서, 생성자가 있는 것과 없는 것이 있는데,

왜 그런가 하는 궁금증이 생겼습니다.

 

 

 

 

 

 

 

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=darae9108&logNo=220701145400 

 

32. 생성자(Constructor)의 사용 개념, 예제/ 생성자 오버로딩(Overloading)

생성자(Constructor)의 사용 : 생성자는 객체가 만들어 질 때 자동으로 호출 되는 메소드이고 일반적인 메...

blog.naver.com

 

생성자는 객체가 만들어 질 때 자동으로 호출 되는 메소드이고, 일반적인 메소드와 몇가지 차이점이 있습니다.

 


 

첫째 : 생성자는 메소드의 반환 자료형이 없습니다.


둘째 : 생성자는 객체가 생성될 때 자동으로 호출 됩니다.


셋째 : 생성자의 이름은 클래스이름과 같습니다.


 

이러한 생성자의 사용용도는 객체의 초기화 과정을 처리하기 위함입니다.
결국 생성자는 객체가 생성될 때 한번만 수행되는 특수한 메소드입니다.

 


이러한 생성자는 new키워드가 수행되면서 생성자가 호출됩니다.

만약 클래스를 정의할 때 생성자를 만들지 않으면 객체 생성시 자바에서 자동으로 생성자를 만들어 줍니다.

 

형식

클래스명() {} => 디폴트 생성자(Default Constructor)

: 메소드의 매개변수와 본문이 전혀 없는 형태입니다.

  이러한 생성자를 디폴트 생성자라 부르고 사용자가
  생성자를 만드지 않아도 자동으로 생성되는 디폴트 생성자가
  있기 때문에 모든 클래스는 최소한 한개의 생성자가 존재합니다. 

 

 

++ 추가 작성예정

 

 

 

 

정리

더보기

1. 빠지는 어노테이션이 있는지 점검하기

-> 테스트 할 때는 @Transactional 을 잊지 않기,

 

2. 문제가 발생할 때는 출력값으로 일일이 점검해보고 이상한 부분을 찾아보기

 

3. 요청의 진행 과정