오늘 한 일
모아요이츠
1. 모든 에러를 GlobalHandler로 AOP처리해봄
2. Swqgger 연결
3. 글 단독조회(상세페이지 조회) 기능 구현
4. 글 카테고리별 전체조회 기능 구현
1. 모든 에러를 GlobalHandler로 AOP 처리해봄
모든 에러를 받는 ErrorHandler를 만들어보고 싶어짐!
// @ExceptionHandler(MethodArgumentNotValidException.class)
// public ApiResponse<List<String>> handleMethodArgumentNotValidException(
// BindingResult bindingResult) {
// List<String> errors = bindingResult.getFieldErrors().stream()
// .map((FieldError fieldError) -> fieldError.getField() +" "+ fieldError.getDefaultMessage())
// .toList();
// return new ApiResponse<>(HttpStatus.BAD_REQUEST.value(), "입력값이 잘못되었습니다", errors);
// }
@ExceptionHandler(Exception.class)
public ApiResponse<String> handleALLException(Exception ex){
return new ApiResponse<>(HttpStatus.BAD_REQUEST.value(), "입력값이 잘못되었습니다", ex.getMessage());
}
이렇게 하고 이메일 형식이 아닌걸로 가입하려 하니까 이렇게 뜬다!
{
"email":"emaildot.com",
"password":"passPASS123",
"checkPassword":"passPASS123",
"nickname":"가나다라"
}
{
"status": 400,
"message": "입력값이 잘못되었습니다",
"data": "Validation failed for argument [0] in public com.moayo.moayoeats.global.dto.ApiResponse<java.lang.Void> com.moayo.moayoeats.domain.user.controller.UserController.signup(com.moayo.moayoeats.domain.user.dto.request.SignupRequest): [Field error in object 'signupRequest' on field 'email': rejected value [emaildot.com]; codes [Email.signupRequest.email,Email.email,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [signupRequest.email,email]; arguments []; default message [email],[Ljakarta.validation.constraints.Pattern$Flag;@3abe50dd,.*]; default message [must be a well-formed email address]] "
}
다시 돌리면 다른 에러들은 밑의것으로 받아지고 MethodArgumentNotValidException 은 원래대로 처리될까?
더 하위의 것이 있으면 그 Handler로 들어가고 구현 안 된 것들만 Exception.class로 들어갔으면 좋겠다!
@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResponse<List<String>> handleMethodArgumentNotValidException(
BindingResult bindingResult) {
List<String> errors = bindingResult.getFieldErrors().stream()
.map((FieldError fieldError) -> fieldError.getField() +" "+ fieldError.getDefaultMessage())
.toList();
return new ApiResponse<>(HttpStatus.BAD_REQUEST.value(), "입력값이 잘못되었습니다", errors);
}
@ExceptionHandler(Exception.class)
public ApiResponse<String> handleALLException(Exception ex){
return new ApiResponse<>(HttpStatus.BAD_REQUEST.value(), "입력값이 잘못되었습니다", ex.getMessage());
}
주석 다시 풀어봄
{
"status": 400,
"message": "입력값이 잘못되었습니다",
"data": [
"email must be a well-formed email address"
]
}
오 이번에는 잘 뜸
2. Swqgger 연결
Swagger 추가함
build.gradle에 추가하기
//Swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2'
인증 필터에서 Swagger api 걸러주기
.requestMatchers("/").permitAll() // 메인 페이지 요청 허가
.requestMatchers("/api/v1/users/sign-up/**").permitAll() // singup이후로 접근 허가
.requestMatchers("/api/v1/users/login/**").permitAll() // singup이후로 접근 허가
.requestMatchers("/v3/api-docs/**", "/swagger-ui/**").permitAll()
.anyRequest().authenticated() // 그 외 모든 요청 인증처리
3. 글 상세 조회 페이지 만들기
public record DetailedPostResponse (
String author,
String address,
String store,
Integer minPrice,
Integer deliveryCost,
List<User> people,
List<List<Menu>> menus,
List<Menu> myMenus,
Integer sumPrice,
LocalDateTime deadline
){
}
//글 단독 조회, 글 상세페이지
@GetMapping("/posts/{postId}")
public ApiResponse<DetailedPostResponse> getPost(
@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable(name = "postId") Long postId
){
return new ApiResponse<>(HttpStatus.OK.value(), "글 상세페이지 조회에 성공했습니다.",postService.getPost(postId, userDetails.getUser()));
}
@Builder
public record DetailedPostResponse (
String author,
String address,
String store,
Integer minPrice,
Integer deliveryCost,
List<Menu> myMenus,
List<String> participants,
List<List<Menu>> menus,
Integer sumPrice,
LocalDateTime deadline
){
}
List 순회하면서 Role이 Host아닌 유저의 닉네임만 걸러낼건데 stream filter쓰고싶어짐!!
https://www.baeldung.com/java-stream-filter-lambda
private List<String> getParticipants(List<UserPost> userPosts){
return userPosts.stream()
.filter((UserPost userPost)->userPost.getRole()==UserPostRole.PARTICIPANT)
.map((UserPost userPost)->userPost.getUser().getNickname()).toList();
}
stream filter 처음 써보는데 엄청 편리한듯!
음 일단 participant는 제대로 되나 찍어봤는데 그것도 null이 돌아가고 있음
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"participants": [], -> 이러시면 안되거든요...
private List<String> getParticipants(List<UserPost> userPosts){
return userPosts.stream()
.filter((UserPost userPost)->userPost.getRole()==UserPostRole.PARTICIPANT)
.map((UserPost userPost)->userPost.getUser().getNickname()).toList();
}
다시보니 ==이라 틀린거같음 equals를 넣어줘야 하는데
equals로 바꿔봄
private List<String> getParticipants(List<UserPost> userPosts){
return userPosts.stream()
.filter((UserPost userPost)->userPost.getRole().equals(UserPostRole.PARTICIPANT))
.map((UserPost userPost)->userPost.getUser().getNickname()).toList();
}
아직도 null값이 돌아감
Collectors.toList() 넣어봄
private List<String> getParticipants(List<UserPost> userPosts){
return userPosts.stream()
.filter((UserPost userPost)->userPost.getRole().equals(UserPostRole.PARTICIPANT))
.map((UserPost userPost)->userPost.getUser().getNickname()).collect(Collectors.toList());
}
"participants": [],
아직도 이래
익명함수 말고 함수를 따로 뺴는 방법)
We can also use a method reference, which is shorthand for a lambda expression:
List<Customer> customersWithMoreThan100Points = customers
.stream()
.filter(Customer::hasOverHundredPoints)
.collect(Collectors.toList());Copy
In this case, we added the hasOverHundredPoints method to our Customer class:
public boolean hasOverHundredPoints() {
return this.points > 100;
}
해봤는데
private List<String> getParticipants(List<UserPost> userPosts){
return userPosts.stream()
.filter(UserPost::isParticipant)
.map((UserPost userPost)->userPost.getUser().getNickname()).toList();
}
public boolean isParticipant(UserPost userpost){
return userpost.getRole().equals(UserPostRole.PARTICIPANT);
}
isParticipant가 빨간색으로 뜸 ㅜㅜ
걍 for문으로 합니다
private List<String> getParticipants(List<UserPost> userPosts){
List<String> participants = new ArrayList<>();
for(UserPost userpost : userPosts){
participants.add(userpost.getUser().getNickname());
}
return participants;
}
음 해결됨
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"participants": [
"가나다라"
],
author은 그냥 빼고 participants에다 host까지 들어가게 바꿈
@Override
public DetailedPostResponse getPost(Long postId, User user) {
Post post = getPostById(postId);
List<UserPost> userPosts = getUserPostsByPost(post);
List<List<Menu>> allMenus = getAllMenus(userPosts,post);
return DetailedPostResponse.builder()
.address(post.getAddress())
.store(post.getStore())
.minPrice(post.getMinPrice())
.deliveryCost(post.getDeliveryCost())
.participants(getParticipants(userPosts))
.menus(allMenus)
.myMenus(getMyMenus(user, allMenus))
.sumPrice(getSumPrice(getUserPostsByPost(post),post))
.deadline(getDeadline(post))
.build();
}
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"participants": [
"가나다라"
],
여기까진 잘 나온다
⛳문제 발생 : 재귀가 끝나지 않음
@Override
public DetailedPostResponse getPost(Long postId, User user) {
Post post = getPostById(postId);
List<UserPost> userPosts = getUserPostsByPost(post);
List<List<Menu>> allMenus = getMenus(userPosts,post);
return DetailedPostResponse.builder()
.author(getAuthor(userPosts))
.address(post.getAddress())
.store(post.getStore())
.minPrice(post.getMinPrice())
.deliveryCost(post.getDeliveryCost())
.participants(getParticipants(userPosts))
.myMenus(getMyMenus(user, allMenus))
.menus(allMenus)
.sumPrice(getSumPrice(getUserPostsByPost(post),post))
.deadline(getDeadline(post))
.build();
}
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"myMenus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
"deliveryCost": 2000,
"category": "KOREAN",
... 이하 반복 후 에러메시지가 출력됨 "menus": [
{
"status": 400,
"message": "에러가 발생했습니다",
"data": "Could not write JSON: Infinite recursion (StackOverflowError)"
}
myMenus가 문제임
private List<Menu> getMyMenus(User user, List<List<Menu>> allMenus){
List<Menu> myMenus = null;
for(List<Menu> menus : allMenus){
if(menus.size()>0){
if(menus.get(0).getUser().getId().equals(user.getId())){
myMenus = menus;
break;
}
}
}
return myMenus;
}
저기에서 뭐가 오류가 나는지 모르겠네?
break가 안 되는건가 싶어서 break대신 return을 해봄
private List<Menu> getMyMenus(User user, List<List<Menu>> allMenus){
for(List<Menu> menus : allMenus){
if(menus.size()>0){
if(menus.get(0).getUser().getId().equals(user.getId())){
return menus;
}
}
}
return null;
}
상황이 똑같음
mymenus가 아니라 allmenus가 문제인가 싶어서 순서를 한번 바꿔봄
@Builder
public record DetailedPostResponse (
String author,
String address,
String store,
Integer minPrice,
Integer deliveryCost,
List<List<Menu>> menus,
List<Menu> myMenus,
List<String> participants,
Integer sumPrice,
LocalDateTime deadline
){
}
return DetailedPostResponse.builder()
.author(getAuthor(userPosts))
.address(post.getAddress())
.store(post.getStore())
.minPrice(post.getMinPrice())
.deliveryCost(post.getDeliveryCost())
.participants(getParticipants(userPosts))
.menus(allMenus)
.myMenus(getMyMenus(user, allMenus))
.sumPrice(getSumPrice(getUserPostsByPost(post),post))
.deadline(getDeadline(post))
.build();
음 바꾸니까 allMenus가 문제였다는 걸 알게됨
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"menus": [
[
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
지금 allMenus가 어떻게 되고 있냐면
List<List<Menu>> allMenus = getMenus(userPosts,post);
private List<List<Menu>> getMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = new ArrayList<>();
for(UserPost userpost : userposts){
List<Menu> myMenus = getUserMenus(userpost.getUser(),post);
menus.add(myMenus);
}
return menus;
}
private List<Menu> getUserMenus(User user, Post post){
return menuRepository.findAllByUserAndPost(user,post);
}
음… 왜 무한반복이 되는거지…
List<List<Menu>> menus = new ArrayList<>(); -> 미부분을 이렇게 쓰면 알아서 안 되는건가?
List<List<Menu>> menus = new ArrayList<List<Menu>>(); 이렇게 바꿔봄
아무 상관 없었음~~
ArrayList 에 add하는게 맞나 싶어서 찾아봄
https://www.baeldung.com/java-list-of-lists
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = new ArrayList<>();
for(UserPost userpost : userposts){
List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
menus.add(userMenus);
}
return menus;
}
private List<String> getParticipants(List<UserPost> userPosts){
return userPosts.stream()
.filter((UserPost userPost)->userPost.getRole().equals(UserPostRole.PARTICIPANT))
.map((UserPost userPost)->userPost.getUser().getNickname()).toList();
}
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = new ArrayList<>();
for(UserPost userpost : userposts){
List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
menus.add(userMenus);
}
return menus;
}
다시봐도 뭐가 잘못되었는지 모르겠고 일단 스트림으로 해봄
→
stream으로 바꾸다보니 List<List<Menu>>에다가 List<ArrayList<Menu>> 넣지 말라고 해서 그 부분 다 수정함
@Builder
public record DetailedPostResponse (
String author,
String address,
String store,
Integer minPrice,
Integer deliveryCost,
List<String> participants,
List<ArrayList<Menu>> menus,
List<Menu> myMenus,
Integer sumPrice,
LocalDateTime deadline
){
}
private List<Menu> getMyMenus(User user, List<ArrayList<Menu>> allMenus){
for(List<Menu> menus : allMenus){
if(menus.size()>0){
if(menus.get(0).getUser().getId().equals(user.getId())){
return menus;
}
}
}
return null;
}
private List<ArrayList<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<ArrayList<Menu>> menus = userposts.stream().map((UserPost userpost)->new ArrayList<>(getUserMenus(userpost.getUser(),userpost.getPost()))).toList();
return menus;
}
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"participants": [],
"menus": [
[
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
오 ~~ 여러가지 시도 다 해봐도 menus는 스트림으로 하나마나 무한반복임
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = userposts.stream().map((UserPost userpost)->getUserMenus(userpost.getUser(),userpost.getPost())).toList();
return menus;
}
이렇게 해봄
상황 똑같음
for문으로 다시 돌아가봄
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = new ArrayList<>();
for(UserPost userpost : userposts){
List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
menus.add(userMenus);
}
return menus;
}
"menus": [
[
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
💡참조에 문제가 있다고 함
menu를 가져올때 post를 가져오고 다시 menu를 가져오고 무한반복의 루프에 빠짐
Post entity에 JSON Ignore를 붙였더니 끝나긴 끝났다 아직 상호참조를 하고있지만…
@OneToMany(mappedBy = "post")
@JsonIgnore//상호참조문제?
private List<Menu> menus;
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"participants": [
"가나다라"
],
"menus": [
[
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"sumPrice": null,
"deadline": "2024-01-09T23:03:49.701351"
},
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 2,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"sumPrice": null,
"deadline": "2024-01-09T23:03:49.701351"
},
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 3,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"sumPrice": null,
"deadline": "2024-01-09T23:03:49.701351"
},
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
}
]
],
"myMenus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"sumPrice": null,
"deadline": "2024-01-09T23:03:49.701351"
},
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 2,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"sumPrice": null,
"deadline": "2024-01-09T23:03:49.701351"
},
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 3,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"sumPrice": null,
"deadline": "2024-01-09T23:03:49.701351"
},
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
}
],
"sumPrice": 15000,
"deadline": "2024-01-09T23:03:49"
}
}
Post entity에서 menus를 그냥 참조해올수 있는데 menu repository에서 해서 문제가 됐던걸까!
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = new ArrayList<>();
for(UserPost userpost : userposts){
List<Menu> userMenus = getUserMenus(userpost.getUser(),post);
menus.add(userMenus);
}
return menus;
}
private List<Menu> getUserMenus(User user, Post post){
return menuRepository.findAllByUserAndPost(user,post);
}
→
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = new ArrayList<>();
for(UserPost userpost : userposts){
List<Menu> userMenus = userpost.getPost().getMenus();
menus.add(userMenus);
}
return menus;
}
이렇게 바꿔봄
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"participants": [
"가나다라"
],
"menus": [
[
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
"id": 1,
"post": {
"id": 1,
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"category": "KOREAN",
"menus": [
{
음 똑같은 문제가 일어난다
⚠️Spring Data JPA, @OneToMany 무한 반복 오류
@OneToMany Entity을 RestAPI로 리턴할때 부한 반복 오류
양방향 관계의 Entity에서 @OneToMany를 사용하면, 엔티티를 리턴할 때 순환 참조(Circular Reference) 문제가 발생할 수 있다고 함!
JSON 직렬화 시 무한 루프 -> StackOverflowError가 발생함 ( 나도 저거 발생했음! )
💡순환참조 해결법
- @JsonIgnore : 이 어노테이션을 붙이면 JSON 데이터에 해당 property는 null로 들어가게 된다. 즉, 데이터에 아예 포함시키지 않는다.
- @JsonManagedReference 와 @JsonBackReference : 부모 클래스(Posts entity)의 Comment 필드에 @JsonManagedReference를, 자식 클래스(Comment entity)의 Posts 필드에 @JsonBackReference를 추가해주면 순환 참조를 막을 수 있다.
- @JsonIgnoreProperties : 부모 클래스(Posts entity)의 Comment 필드에 @JsonIgnoreProperties({"posts"}) 를 붙여주면 순환 참조를 막을 수 있다.
- DTO 사용 : 위와 같은 상황이 발생하게된 주원인은 '양방향 매핑'이기도 하지만, 더 정확하게는 Entity 자체를 response로 리턴한데에 있다. entity 자체를 return 하지 말고, DTO 객체를 만들어 필요한 데이터만 옮겨담아 Client로 리턴하면 순환 참조 관련 문제는 애초에 방지 할 수 있다.
- 양방향 매핑을 단방향 매핑으로
🚩해결 : @JsonManagedReference 와 @JsonBackReference 달아서 해결함!!
public class Menu {
@JsonBackReference
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "post_id", nullable = false)
private Post post;
public class Post {
@JsonManagedReference
@OneToMany(mappedBy = "post")
private List<Menu> menus;
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"participants": [
"가나다라"
],
"menus": [
[
{
"id": 1,
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 2,
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 3,
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
}
]
],
"myMenus": [
{
"id": 1,
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 2,
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
},
{
"id": 3,
"user": {
"id": 1,
"email": "email@dot.com",
"password": "$2a$10$lGhYCvjkDNzZyq8RkanrZ.3NRctUwVvZAbS8c9sFepIFz7U6wJUUq",
"nickname": "가나다라"
},
"menuname": "통새우버거",
"price": 5000
}
],
"sumPrice": 15000,
"deadline": "2024-01-09T23:03:49"
}
}
잘 나온다!!
다시 Stream으로 바꿔봄
private List<List<Menu>> getAllMenus(List<UserPost> userposts, Post post){
List<List<Menu>> menus = userposts.stream().map((UserPost userpost)->getUserMenus(userpost.getUser(),userpost.getPost())).toList();
return menus;
}
post 필요없는거 같아서 삭제함
private List<List<Menu>> getAllMenus(List<UserPost> userposts){
List<List<Menu>> menus = userposts.stream().map((UserPost userpost)->userpost.getPost().getMenus()).toList();
return menus;
}
잘된다!
💡생각해봄
userpost.getPost().getMenus()랑 post.getMenus()랑 JPA내부적으로 생각해보면 동일한듯
userpost에 있는 postId로 post를 찾아와서 그걸로 tb_menu에서 menu들 찾아오나
post에 있는 postId로 post를 찾아와서 그걸로 tb_menu에서 menu들 찾아오나
근데 애초에 dto를 쓰는데 이유가 있었네ㅋㅋ
Menu를 안 돌려보내고 Menu response를 돌려보냈으면 이럴 일이 애초에 없고 user 정보도 안 나올거잖아...
User 정보가 왜 써있나 했다
Menu에 User가 들어있으니까 그걸 또 쓴거구나
Menu에 Post가 들어있으니까 그거 정보 쓰다가 그 안에 Menu가 있으니까 그거 쓰다가 무한반복이 그래서 시작된거군….
뭔가 DetailedPostResponse 짜는 중 무의식중에 dto안 만들고 그냥 Menu를 돌려보냈었는데 앞으로는 절대 그럴 일이 없을듯 ㅋㅋㅋ
🚩💡더 나은 해결책
public record MenuResponse(
String menuname,
Integer price
) {
}
public record MenusResponse(
String nickname,
List<MenuResponse> menus
) {
}
걍 참여자 이름도 따로 넣지 않고 메뉴에다 넣고 myMenus를 없애고 allMenus 하나로 하는게 좋을듯
@Builder
public record DetailedPostResponse (
String address,
String store,
Integer minPrice,
Integer deliveryCost,
List<List<MenuResponse>> menus,
Integer sumPrice,
LocalDateTime deadline
){
}
private List<MenusResponse> getAllMenus(List<UserPost> userposts){
List<MenusResponse> menus = userposts.stream().map((UserPost userpost)->
new MenusResponse(userpost.getUser().getNickname(),
userpost.getPost().getMenus()
.stream().map((Menu menu)->new MenuResponse(menu.getMenuname(),menu.getPrice())).toList()
)).toList();
return menus;
}
{
"status": 200,
"message": "글 상세페이지 조회에 성공했습니다.",
"data": {
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"deliveryCost": 2000,
"menus": [
{
"nickname": "가나다라",
"menus": [
{
"menuname": "통새우버거",
"price": 5000
},
{
"menuname": "통새우버거",
"price": 5000
},
{
"menuname": "통새우버거",
"price": 5000
}
]
}
],
"sumPrice": 15000,
"deadline": "2024-01-09T23:03:49"
}
}
잘 된다!!
4. 글 카테고리별 조회
public record PostCategorySearchRequest (
CategoryEnum categoty
){
}
package com.moayo.moayoeats.domain.post.entity;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum CategoryEnum {
ALL("전체"),
BURGER("햄버거"),
CHICKEN("치킨"),
PIZZA("피자"),
KOREAN("한식"),
SNACK("분식"),
WESTERN("양식"),
ASIAN("아시안"),
JAPANESE("일식"),
CHINESE("중식"),
LUNCHBOX("도시락");
private final String category;
}
💡저 CategoryEnum을 Bean Validation하는 방법도 있을까??
저 Enum이 아닌 값이 날아오면 에러 던지는거임
찾아보니 개발자가 직접 정의한 Enum class의 경우는 Validation 방법 또한 개발자가 직접 추가해야 한다고 함
- 먼저 Enum annotation을 작성한다!
package com.moayo.moayoeats.domain.post.exception.validator;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER,TYPE_USE})
@Retention(RUNTIME)
@Constraint(validatedBy = {EnumValidator.class})
public @interface Enum {
String message() default "the value should be one of the Enum";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
Class<? extends java.lang.Enum<?>> enumClass();
boolean ignoreCase() default false;
}
package com.moayo.moayoeats.domain.post.exception.validator;
import jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class EnumValidator implements ConstraintValidator<Enum,String> {
private Enum annotation;
@Override
public void initialize(Enum constraintAnnotation){
this.annotation = constraintAnnotation;
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
Object[] enumValues = this.annotation.enumClass().getEnumConstants();
if (enumValues != null) {
for (Object enumValue : enumValues) {
if (value.equals(enumValue.toString())
|| (this.annotation.ignoreCase() && value.equalsIgnoreCase(enumValue.toString()))) {
return true;
}
}
}
return false;
}
}
annotation적용해주기
public record PostCategorySearchRequest (
@Enum(enumClass = CategoryEnum.class)
CategoryEnum categoty
){
}
🚩문제 . 왜 @Enum에 빨간줄이 뜨나요?
예측 1. class는 되는데 record는 안 된다
예측 2. import가 안 되어서 안 된다
import com.moayo.moayoeats.domain.post.exception.validator.Enum;
내가 정의한 Enum annotation import문 추가해주니까 안 뜬다!!
🚩문제 : Bean creation error막 이러면서 난리남
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'postController' method
com.moayo.moayoeats.domain.post.controller.PostController#getPosts(UserDetailsImpl)
to {GET [/api/v1/posts]}: There is already 'postController' bean method
com.moayo.moayoeats.domain.post.controller.PostController#getPostsByCategory(UserDetailsImpl, PostCategoryRequest) mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.validateMethodMapping(AbstractHandlerMethodMapping.java:667) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:633) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:331) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:486) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:79) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lambda$detectHandlerMethods$2(AbstractHandlerMethodMapping.java:298) ~[spring-webmvc-6.1.2.jar:6.1.2]
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:296) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.processCandidateBean(AbstractHandlerMethodMapping.java:265) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:224) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:212) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:233) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1820) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1769) ~[spring-beans-6.1.2.jar:6.1.2]
... 67 common frames omitted
public record PostCategoryRequest(
//@Enum(enumClass = CategoryEnum.class)
CategoryEnum categoty
){
}
Enum 주석처리해봄
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'postController' method
com.moayo.moayoeats.domain.post.controller.PostController#getPostsByCategory(UserDetailsImpl, PostCategoryRequest)
to {GET [/api/v1/posts]}: There is already 'postController' bean method
com.moayo.moayoeats.domain.post.controller.PostController#getPosts(UserDetailsImpl) mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.validateMethodMapping(AbstractHandlerMethodMapping.java:667) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:633) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:331) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:486) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:79) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lambda$detectHandlerMethods$2(AbstractHandlerMethodMapping.java:298) ~[spring-webmvc-6.1.2.jar:6.1.2]
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:296) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.processCandidateBean(AbstractHandlerMethodMapping.java:265) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:224) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:212) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:233) ~[spring-webmvc-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1820) ~[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1769) ~[spring-beans-6.1.2.jar:6.1.2]
... 67 common frames omitted
똑같음
to {GET [/api/v1/posts]}: There is already 'postController' bean method
아 내가 다른 인텔리제이 창 실행시키고 있었나봄
아니었다
뭐가 문제일까
구글링해보니까 내가 PostController에서 똑같은 api, 똑같은 mapping으로 보내는게 두개라서 깨지는거라고 함
// 모든 글 조회하기
@GetMapping("/posts")
public ApiResponse<List<BriefPostResponse>> getPosts(
@AuthenticationPrincipal UserDetailsImpl userDetails
){
return new ApiResponse<>(HttpStatus.OK.value(), "모든 글 조회에 성공했습니다.",postService.getPosts(userDetails.getUser()));
}
저기에서 이미 /posts를 쓰고있는데 또 쓰려고 했다…
⛳해결 : 중복되던 api 주소 서로 다르게 바꿔줌!
그리고 Custon Enum Validation도 해보게 @Valid도 달아봄~
//글 카테고리별 조회
@GetMapping("/posts/category")
public ApiResponse<List<BriefPostResponse>> getPostsByCategory(
@AuthenticationPrincipal UserDetailsImpl userDetails,
@Valid @RequestBody PostCategoryRequest postCategorySearchReq
){
return new ApiResponse<>(HttpStatus.OK.value(), "글 카테고리별 조회에 성공했습니다.",postService.getPostsByCategory(postCategorySearchReq, userDetails.getUser()));
}
{
"status": 400,
"message": "에러가 발생했습니다",
"data": "HV000030: No validator could be found for constraint 'com.moayo.moayoeats.domain.post.exception.validator.Enum' validating type 'com.moayo.moayoeats.domain.post.entity.CategoryEnum'. Check configuration for 'categoty'"
}
ㅜㅜ 오류발생함
public record PostCategoryRequest(
// @Enum(enumClass = CategoryEnum.class)
CategoryEnum categoty
){
}
Enum 일단 주석처리함!
{
"category":"All"
}
public record PostCategoryRequest(
// @Enum(enumClass = CategoryEnum.class)
CategoryEnum categoty
){
}
{
"status": 400,
"message": "에러가 발생했습니다",
"data": "Cannot invoke \\"com.moayo.moayoeats.domain.post.entity.CategoryEnum.getCategory()\\" because the return value of \\"com.moayo.moayoeats.domain.post.dto.request.PostCategoryRequest.categoty()\\" is null"
}
왜 안돼..?
dto에 categoty로 오타남 ㅋㅋ
오타 수정하고 다시 해봄
{
"category":"ALL"
}
{
"status": 200,
"message": "글 카테고리별 조회에 성공했습니다.",
"data": []
}
🚩문제 : db조회가 안 됨
{
"category":"KOREAN"
}
{
"status": 200,
"message": "글 카테고리별 조회에 성공했습니다.",
"data": []
}
@Override
public List<BriefPostResponse> getPostsByCategory(
PostCategoryRequest postCategoryReq,
User user
) {
List<Post> posts;
if(postCategoryReq.category().getCategory().equals(CategoryEnum.ALL)){
posts = findAll();
}else{
posts = postRepository.findAllByCategoryEquals(postCategoryReq.category()).orElse(null);
}
return postsToBriefResponses(posts);
}
이걸 들여다보면 if나 else가 제대로 동작을 안 했을때
List<Post> posts;
return postsToBriefResponses(posts);
만 수행되면 null이 돌아감
Enum은 equals쓰는거 아닌가??
Enum 비교 ==인지 equals인지 갑자기 헷갈려서 찾아봄
둘 다 된다고 함
⭐Enum equals()와 == 의 차이점
== never throws NullPointerException
== is subject to type compatibility check at compile time
postCategoryReq.category().getCategory().equals(CategoryEnum.ALL
인텔리제이가 이 문장이 언제나 false라고 함
왜…??!!
posts = postRepository.findAllByCategoryEquals(postCategoryReq.category().getCategory())
else안도 이렇게 바꿔봤는데
postCategoryReq.category().getCategory())
여기에 빨간줄이 그어짐!
인텔리제이가 expected type이 CategoryEnum인데 provided가 String이라고 함
그리고 CateforyEnum.valueOf를 대신 써보라고 함
예전 프로젝트에서는 Enum 만들때
걍 이렇게 만들어서 썼었는데
public enum CategoryEnum {
ALL,
BURGER,
CHICKEN),
PIZZA,
KOREAN,
SNACK,
WESTERN,
ASIAN,
JAPANESE,
CHINESE,
LUNCHBOX;
}
이번에는 String category를 만들어봐서 저런 문제가 발생한 거 같다..!
근데 아무데도 안 쓰는 저 String을 왜 해놨는지 의문이긴 함
public enum CategoryEnum {
ALL("전체"),
BURGER("햄버거"),
CHICKEN("치킨"),
PIZZA("피자"),
KOREAN("한식"),
SNACK("분식"),
WESTERN("양식"),
ASIAN("아시안"),
JAPANESE("일식"),
CHINESE("중식"),
LUNCHBOX("도시락");
private final String category;
}
db에 String을 저장하고 싶어서 저랬던 거 같은데
지금 db를 들어가서 보니 KOREAN으로 넣은게 3이라는 Enum으로 들어가있음
@Column
@Enumerated(EnumType.STRING)
private CategoryEnum category;
이렇게 바꿔봄
테이블 드랍하고 새로 Post 생성해봄
posts = postRepository.findAllByCategoryEquals(postCategoryReq.category().getCategory()).orElse(null);
여기서 에러나서 빌드가 안 됨
public interface PostRepository extends JpaRepository<Post, Long> {
Optional<List<Post>> findAllByCategoryEquals(CategoryEnum category);
}
이걸 수정함
Optional<List<Post>> findAllByCategoryEquals(String category);
새로 Post 생성해서 넣어봄
KOREAN으로 잘 들어가있음!!
{
"status": 400,
"message": "에러가 발생했습니다",
"data": "Argument [한식] of type [java.lang.String] did not match parameter type [com.moayo.moayoeats.domain.post.entity.CategoryEnum (n/a)]"
}
오
이렇게 해봄
{
"category":"한식"
}
{
"status": 400,
"message": "에러가 발생했습니다",
"data": "JSON parse error: Cannot deserialize value of type `com.moayo.moayoeats.domain.post.entity.CategoryEnum` from String \\"한식\\": not one of the values accepted for Enum class: [ALL, WESTERN, ASIAN, BURGER, PIZZA, CHINESE, SNACK, LUNCHBOX, CHICKEN, JAPANESE, KOREAN]"
}
ㅋㅋㅋㅋ
걍 “한식”부분 다 빼고 그냥 예전처럼 String 대신 그냥 Enum 이름만 있게 함
posts = postRepository.findAllByCategoryEquals(postCategoryReq.category().getCategory()).orElse(null);
→
posts = postRepository.findAllByCategoryEquals(postCategoryReq.category()).orElse(null);
이거 바꾸고
public interface PostRepository extends JpaRepository<Post, Long> {
Optional<List<Post>> findAllByCategoryEquals(String category);
}
→
Optional<List<Post>> findAllByCategoryEquals(CategoryEnum category);
이것도 바꿈
이렇게 해두면 숫자일거같은데…
Enum 바뀌거나 db 변경사항 있을때 큰일나지 않나?
Post 생성하고 앞번호에 Enum하나 추가한다음에 다시 찾아봄
{
"status": 200,
"message": "글 카테고리별 조회에 성공했습니다.",
"data": [
{
"id": 1,
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"sumPrice": 5000,
"deadline": "2024-01-11T00:41:48"
},
{
"id": 2,
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"sumPrice": 10000,
"deadline": "2024-01-11T00:41:49"
},
{
"id": 3,
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"sumPrice": 5000,
"deadline": "2024-01-11T00:41:50"
}
]
}
KOREAN으로 등록해둔거임
@Getter
@RequiredArgsConstructor
public enum CategoryEnum {
TEST,
ALL,
BURGER,
CHICKEN,
PIZZA,
KOREAN,
SNACK,
WESTERN,
ASIAN,
JAPANESE,
CHINESE,
LUNCHBOX;
}
TEST를 추가해봄
그리고 다시 조회해보니까 똑같이 나옴
{
"status": 200,
"message": "글 카테고리별 조회에 성공했습니다.",
"data": [
{
"id": 1,
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"sumPrice": 5000,
"deadline": "2024-01-11T00:41:48"
},
{
"id": 2,
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"sumPrice": 10000,
"deadline": "2024-01-11T00:41:49"
},
{
"id": 3,
"author": "가나다라",
"address": "주소주소",
"store": "storestore",
"minPrice": 20000,
"sumPrice": 5000,
"deadline": "2024-01-11T00:41:50"
}
]
}
String으로 등록했을때 Enum으로 equals하는건 숫자 대신 String으로 해주나봄!
'개발일지' 카테고리의 다른 글
2024-01-12, Today I Learned (0) | 2024.01.12 |
---|---|
2024-01-11, Today I Learned (1) | 2024.01.11 |
2024-01-09, Today I Learned @IdClass Composite key in Spring (0) | 2024.01.09 |
2024-01-08, Today I Learned (1) | 2024.01.08 |
2024-01-03, Today I Learned (0) | 2024.01.03 |