'지난 주 카페 글 중 좋아요를 가장 많이 받은 사람 1명' 에 대한 API 를 만들고 있다
JPA의 기본 기능이 아닌 JPA의 native query를 사용해야할 것 같다
그래서 가장 먼저 쿼리를 만들었다
BETWEEN에는 지난주 월요일, 지난주 토요일 날짜가 들어가야하지만, 현재는 이에 해당하는 데이터가 없기에데이터가 있는 날짜로 범위를 좁혔다(오로지 테스트를 위해)
SELECT
r.user_id, rl.recipe_id,
count(rl.user_id) AS like_count
FROM recipe_like rl, recipe r
WHERE rl.recipe_id = r.recipe_id
AND rl.reg_date BETWEEN '2021-11-16 10:36:02.741931' AND '2021-11-23 12:53:13.741931'
GROUP BY rl.recipe_id
ORDER BY like_count DESC
LIMIT 1;
recipe_like 테이블엔 recipe_id, user_id 컬럼이 있다
해당 게시물(=레시피)에 좋아요를 누르면 어느 user가 어느 recipe를 좋아요 눌렀는지 insert 된다
recipe 테이블엔 어느 유저가 글을 작성했는 지 데이터가 있다
특정 시간대에 사용자가 특정 게시물에 좋아요를 누른 개수를 알아내야 하고
그 게시물을 작성한 사용자를 알아내야 하기 때문에 위와 같이 쿼리를 짰다.
지금까지 한 테이블에 대한 쿼리를 JPA로 짜면 리턴 형식이 예를 들어
List<Board>, List<BoardComment> 등 제너릭에 테이블 이름이 들어갔다
하지만 여기서 문제점은 위의 결과처럼 user_id, recipe_id, like_count 컬럼을 가진 테이블(JPA로는 엔티티)가 없다
어떻게 리턴해야하지? 라는 생각이 들었다
https://kwonnam.pe.kr/wiki/java/jpa/nativequery
java:jpa:nativequery [권남]
kwonnam.pe.kr
다중 Entity를 결과로 받는 Native Query는 @SqlResultSetMapping로 매핑 정보를 지정해야 하며
그 결과는 List<Object[]>로 리턴한다.
라고 적혀있다
그래서 내가 고민하고 있는 상황에 대한 답은 'List<Object[]>로 반환해야한다' 이다
Object[]가 어떻게 찍히는 지 디버그를 찍어봤다
왜 Object가 아닌 Object[] 일까 라는 생각을 1초정도 했지만 여기서 해결되었다
user_id = 2, recipe_id = 1, like_count = 3 이런 식으로 맵핑되는게 아니라
0번째 = 2, 1번째 = 1, 2번째 = 3 이런 식으로 맵핑되서 나오는 것이다
@SqlResultSetMapping을 쓰라는 이유가 있었다
@SqlResultSetMapping 어노테이션을 쓰지 않으면 바로 위에서 말한 내용처럼 0번째, 1번째, 2번째로 나오기 때문이다
어노테이션을 사용하면 user_id = 2, recipe_id = 1, like_count = 3 이런 식으로 맵핑되어 나오게 할 수 있다
하지만 난 쓰지 않았다
리턴하는 것이 어떤 데이터를 의미하는지 알 수 있겠지만, 어노테이션을 쓰면 하나의 쿼리를 조회하는데 훨씬 더 복잡해보이고 길어보이기 때문이다..ㅎ로직에서 맵핑에 대한 것을 처리했다
//user_Id
BigInteger userIdBigInteger = (BigInteger) object[0];
//recipe_id
BigInteger recipeIdBigInteger = (BigInteger) object[1];
//like_count
BigInteger likeCountBigInteger = (BigInteger) object[2];
이런 식으로 꺼내오면 되기 때문에 문제 없다고 생각한다
[Java 저번 주 날짜 구하기]
이 글을 참고했다
자바8의 java.time 패키지(LocalDate, LocalTime, LocalDateTime 등)
예전에 JPA와 LocalDate, LocalDateTime 사용하기 에서 자바8에서 추가된 새로운 날짜와 시간에 대한 API에 대해서 간단하게 글을 썼었다. 이번에는 자바8에 추가된 날짜와 시간 API에 대해서 조금 더 자세
blog.eomdev.com
위 글을 보고 이렇게 짰다
String dateStr = "2021-11-24 10:36:02"; //테스트 데이터
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.parse(dateStr, formatter);
//저번 주 월요일
LocalDateTime lastMonday = now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
//저번 주 일요일
LocalDateTime lastSunday = lastMonday.plusDays(6);
하지만 오늘이 11/24 일 경우, lastMonday는 가장 최근의 월요일이였던 11/22 이 나온다
지난주 월요일에서 6일을 더했기 때문에 lastSunday는 11/28 이 나온다
가장 최근에 지나간 월요일 말고...! 전 주 월요일을 구하고 싶다
String dateStr = "2021-11-24 10:36:02"; //테스트 데이터
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.parse(dateStr, formatter);
//저번 주 월요일
LocalDateTime lastMonday = now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY)).minusDays(7);
//저번 주 일요일
LocalDateTime lastSunday = lastMonday.plusDays(6);
그래서 -7일을 했다
그랬더니 저번주 월요일인 11/15 가 나왔다
저번주 일요일도 11/21로 나왔다
하지만 더 테스트 해 보아야할 것은
현재가 월요일(11/22)일 때 어떻게 나오는 지 봐야 한다
String dateStr = "2021-11-22 10:36:02"; //테스트 데이터
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.parse(dateStr, formatter);
//저번 주 월요일
LocalDateTime lastMonday = now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY)).minusDays(7);
//저번 주 일요일
LocalDateTime lastSunday = lastMonday.plusDays(6);
lastMonday가 11/08이 나온다..!
왜 2주 전 월요일이 나오지???했지만
이걸로 해결이 되었다
String dateStr = "2021-11-22 10:36:02"; //테스트 데이터
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.parse(dateStr, formatter);
//저번 주 월요일 : 지난갔던 가장 최근의 월요일에서 7일 빼기
LocalDateTime lastMonday = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7);
//저번 주 일요일 : 지나갔던 가장 최근의 월요일에서 7일 뺀 상태에서 6일 더하기
LocalDateTime lastSunday = lastMonday.plusDays(6);
previousOrSame을 사용한다면 저번 주 월요일은 11/15 가 나온다!
자연스럽게 저번 주 일요일도 11/21 이 나온다
previousOrSame은 오늘을 포함해서 지난 요일을 구하는 함수이다
11/22 을 포함해서 지난 월요일을 구했기 때문에 11/08 이 아닌 11/15가 나온다
생각 못 했던 게 있다!
바로 위의 내용을 보면 현재 날짜에서 저번주 월요일 ~ 일요일 날짜를 구하는데
날짜는 바뀌었지만 시/분/초는 바뀌지 않았다!
그거까지는 생각 못 했다
String dateStr = "2021-12-01 10:36:02"; //테스트 데이터
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.parse(dateStr, formatter);
//저번 주 월요일 : 지난갔던 가장 최근의 월요일에서 7일 빼기
LocalDateTime lastMonday = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).minusDays(7)
.withHour(0).withMinute(0).withSecond(0);
//저번 주 일요일 : 지나갔던 가장 최근의 월요일에서 7일 뺀 상태에서 6일 더하기
LocalDateTime lastSunday = lastMonday.plusDays(6).withHour(23).withMinute(59).withSecond(59);
기존 코드에서 withHour, withMinute, withSecond가 추가된 것 뿐이다
저번 주 순위를 매기려면 저번주 월요일 오전 12시부터 일요일 23시 59분 59초까지 범위를 지정해야 한다
수정 전 코드에서 만약 현재 시간이 2021-11-24 20:52:25 라고 가정한다면
저번주 월요일은 2021-11-15 20:52:25, 저번주 일요일은 2021-11-21 20:52:25 로 된다
이렇게 된다면 빠진 시간이 생기는 것이다
'항해99 3기' 카테고리의 다른 글
[TIL] 2021.11.26 최종 프로젝트 진행중 - CORS 관련 자료 / Nginx 사진 업로드 제한 / 정식 오픈 후 첫 이슈 (0) | 2021.11.26 |
---|---|
[TIL] 2021.11.25 ~ 26 최종 프로젝트 진행중 - EC2 https 적용 (2) | 2021.11.26 |
[TIL] 2021.11.23 최종 프로젝트 진행중 - tomcat에 SSL 적용 /대표님과 면담 (0) | 2021.11.24 |
[TIL] 2021.11.22 최종 프로젝트 진행중 - TDD란? / 오늘의 후회 / 내일 해야할 일 / Tomcat SSL (0) | 2021.11.22 |
[TIL] 2021.11.21 최종 프로젝트 진행중 - 오랜만에 쉬는 일요일 (0) | 2021.11.21 |