Skip to content
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
24ca061
chore: 컨벤션에 위배된 메서드 네임 수정
7zrv Jan 14, 2025
3d3bb57
depend: queryDsl의 SQLExpression 사용을 위한 의존성 추가
7zrv Jan 16, 2025
627720f
chore: 테스트 클래스명 수정
7zrv Jan 16, 2025
9a0702f
feat: 전체, 월별, 주간 봉사 시간 랭킹 쿼리 구현
7zrv Jan 16, 2025
902d44c
feat: 랭킹 계산 유스케이스 구현
7zrv Jan 16, 2025
a754527
feat: 랭킹 캐싱을 위한 redis 레포지토리와 유스케이스 구현
7zrv Jan 16, 2025
92a6ce4
feat: 랭킹 계산, 캐싱을 위한 스케줄러 구현
7zrv Jan 16, 2025
0be813a
feat: 봉사 랭킹 조회 유스케이스 구현
7zrv Jan 16, 2025
e65c87d
feat: 테스트용 DB 설정 추가
7zrv Jan 16, 2025
c2c8e0d
feat: 누락된 테스트 클래스 추가
7zrv Jan 16, 2025
33c7151
feat: test container 추가
7zrv Jan 17, 2025
756d27e
chore: application-test.yml 수정
7zrv Jan 17, 2025
26da3b0
refactor: 랭킹 산출 쿼리 리팩토링
7zrv Jan 17, 2025
366523b
feat: 봉사 랭킹 엔드 포인트 구현
7zrv Jan 17, 2025
4abb947
feat: 봉사 시간 랭킹 스케줄러 로깅 추가
7zrv Jan 17, 2025
482ddfa
refactor: 봉사 시간 랭킹 반환 예외 메세지 수정
7zrv Jan 17, 2025
b753096
feat: 봉사자 닉네임 리스트 반환 쿼리 메서드 생성
7zrv Jan 18, 2025
b627ba1
feat: 봉사자 닉네임 리스트 반환 유스케이스 구현
7zrv Jan 18, 2025
d32c9e0
chore: 봉사자 닉네임 반환 관련 클래스의 명시적인 이름 수정
7zrv Jan 18, 2025
81a1e1c
feat: 봉사 시간 랭킹 Dto nickname 필드 추가
7zrv Jan 18, 2025
98fa3af
refactor: 봉사자 닉네임 반환 유스케이스 리팩토링
7zrv Jan 18, 2025
e2ec50d
refactor: 봉사자 닉네임 반환 유스케이스 리팩토링
7zrv Jan 18, 2025
529ec4f
refactor: 봉사 랭킹의 닉네임 필드 추가에 따른 테스트 수정
7zrv Jan 18, 2025
eeaf438
refactor: 봉사 랭킹 객체 맵퍼 리팩토링
7zrv Jan 18, 2025
5587c96
refactor: 봉사 시간 랭킹 유스케이스 리팩토링
7zrv Jan 18, 2025
c27cfbc
chore: 불필요한 클래스 삭제및 build.gradle 개행 수정
7zrv Jan 19, 2025
9f4953d
feat: test container 설정 추가
7zrv Jan 19, 2025
b6d7ac5
fix: 에러 발생 test 수정
7zrv Jan 19, 2025
78e3cf1
chore: cicd workflow 수정
7zrv Jan 19, 2025
c91552e
fix: ci 파이프 라인 수정
7zrv Jan 19, 2025
f2ff999
fix: ci 파이프 라인 수정
7zrv Jan 19, 2025
cb62123
fix: ci 파이프 라인 수정
7zrv Jan 19, 2025
450d909
fix: 봉사시간 계산 테스트 날짜 수정
7zrv Jan 19, 2025
0914343
fix: ci 테스트 레포트 분석을 위한 설정 추가
7zrv Jan 19, 2025
03126bd
fix: 동시성 테스트 스레드 획득 에러 수정
7zrv Jan 19, 2025
e625296
fix: cicd 빌드 로그 옵션 제거
7zrv Jan 19, 2025
e6e3077
fix: 에러 발생 테스트 주석처리
7zrv Jan 19, 2025
9a9331c
chore: 불필요한 구문 제거및 개행 추가
7zrv Jan 19, 2025
4557b6d
chore: 코드 리뷰사항 반영
7zrv Jan 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions .github/workflows/CD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ jobs:
build-and-push:
runs-on: ubuntu-latest

services:
redis:
image: redis
ports:
- 6379:6379

env:
DB_URL: ${{ secrets.DB_URL }}
DB_USERNAME: ${{ secrets.DB_USERNAME }}
Expand Down Expand Up @@ -43,6 +37,16 @@ jobs:
ELASTIC_PASSWORD: ${{ secrets.ELASTIC_PASSWORD }}
LOKI_URL: ${{ secrets.LOKI_URL }}

TESTCONTAINERS_REUSE_ENABLE: true
TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: /var/run/docker.sock
DOCKER_HOST: unix:///var/run/docker.sock

services:
redis:
image: redis
ports:
- 6379:6379

steps:
- name: Github Repository 파일 불러오기
uses: actions/checkout@v4
Expand Down
32 changes: 20 additions & 12 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
name: CI Pipeline

on:
push:
branches:
[ main ]
Comment on lines -4 to -6
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

push 는 왜 지우셨는지 여쭤보고 싶습니다~

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

같은 로직을 두번 반복하는게 효율적이지 못하다는 생각이 들었고
이미 pr에서 CI를 하며 검증이 되었다고 생각해서 지웠습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋아요~ 확인했습니다

pull_request:
branches:
[ main ]
Expand All @@ -14,14 +11,6 @@ jobs:
Continuous-Integration:
runs-on: ubuntu-latest

#Action 환경에서 Redis 실행을 위한 설정 추후 서버 배포시 제거 예정
services:
redis:
image: redis
ports:
- 6379:6379


env:
DB_URL: ${{ secrets.DB_URL }}
DB_USERNAME: ${{ secrets.DB_USERNAME }}
Expand Down Expand Up @@ -51,13 +40,25 @@ jobs:
ELASTIC_PASSWORD: ${{ secrets.ELASTIC_PASSWORD }}
LOKI_URL: ${{ secrets.LOKI_URL }}

TESTCONTAINERS_REUSE_ENABLE: true
TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: /var/run/docker.sock
DOCKER_HOST: unix:///var/run/docker.sock

services:
redis:
image: redis
ports:
- 6379:6379

steps:
- name: Github Repository 파일 불러오기
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Docker
uses: docker/setup-buildx-action@v3

- name: JDK 21 버전 설치
uses: actions/setup-java@v4
with:
Expand Down Expand Up @@ -88,6 +89,13 @@ jobs:
- name: 빌드 및 테스트
run: ./gradlew build

- name: 테스트 레포트 저장
if: ${{ always() }}
uses: actions/upload-artifact@v3
with:
name: test-reports
path: build/reports/tests/test

- name: Close PR, if build fail
if: ${{ failure() }}
uses: actions/github-script@v6
Expand All @@ -113,6 +121,6 @@ jobs:

- name: SonarCloud 빌드및 분석
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ./gradlew build sonar --info
14 changes: 12 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ dependencies {

// Querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
implementation 'com.querydsl:querydsl-sql:5.0.0'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
Expand Down Expand Up @@ -79,6 +80,10 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation group: 'org.testcontainers', name: 'testcontainers', version: '1.20.4'
testImplementation group: 'org.testcontainers', name: 'junit-jupiter', version: '1.20.4'
testImplementation group: 'org.testcontainers', name: 'mysql', version: '1.20.4'

}

// Querydsl 설정
Expand All @@ -103,6 +108,7 @@ tasks.named('test') {
useJUnitPlatform()
jvmArgs("-XX:+EnableDynamicAgentLoading")
if (gradle.startParameter.taskNames.contains('build')) {
exclude '**/*ControllerTest.class'
finalizedBy 'jacocoTestReport'
}
}
Expand Down Expand Up @@ -131,7 +137,9 @@ def jacocoExcludePatterns = [
'**/fixture/*',
'**/*Factory*',
'**/event/**',
'**/*Aspect*'
'**/*Aspect*',
'**/Aspect/*',
'**/utils/*'
]

def jacocoExcludePatternsForVerify = [
Expand All @@ -151,7 +159,9 @@ def jacocoExcludePatternsForVerify = [
'*.fixture.*',
'*.*Factory*',
'*.*event*.*',
'*.*Aspect*'
'*.*Aspect*',
'*.Aspect.*',
'*.utils.*'
]

jacocoTestReport {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ private Optional<Volunteer> findOne(BooleanExpression condition) {
condition,
isNotDeleted()
)
.fetchOne()
.fetchFirst()
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.somemore.domains.volunteerrecord.controller;

import com.somemore.domains.volunteerrecord.dto.response.VolunteerRankingResponseDto;
import com.somemore.domains.volunteerrecord.usecase.GetVolunteerRankingUseCase;
import com.somemore.global.common.response.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@Tag(name = "Volunteer Ranking API", description = "봉사 시간 랭킹 API")
@RequiredArgsConstructor
@RequestMapping("/api/volunteerrecord")
@RestController
public class VolunteerRankingApiController {

private final GetVolunteerRankingUseCase getVolunteerRankingUseCase;

@Operation(summary = "봉사 시간 랭킹", description = "봉사 시간 랭킹을 반환합니다.")
@GetMapping("/ranking")
public ApiResponse<VolunteerRankingResponseDto> updateCenterProfile() {

VolunteerRankingResponseDto volunteerRankings = getVolunteerRankingUseCase.getVolunteerRanking();

return ApiResponse.ok(volunteerRankings,"봉사 시간 랭킹 반환 성공");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.somemore.domains.volunteerrecord.dto.response;

import java.util.UUID;

public record VolunteerMonthlyRankingResponseDto(
UUID volunteerId,
int totalHours,
long ranking,
String nickname
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.somemore.domains.volunteerrecord.dto.response;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.somemore.domains.center.dto.response.PreferItemResponseDto;
import lombok.Builder;

import java.util.List;

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Builder
public record VolunteerRankingResponseDto(
List<VolunteerTotalRankingResponseDto> volunteerTotalRankingResponse,
List<VolunteerMonthlyRankingResponseDto> volunteerMonthlyResponse,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

얘만 Ranking이 빠진 거 같은데 혹시 다른 의도가 있으신건가용?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아닙니다! 그냥... 바빴나봐요 찾아주셔서 감사합니다 ㅎㅎ

List<VolunteerWeeklyRankingResponseDto> volunteerWeeklyRankingResponse
) {
public static VolunteerRankingResponseDto of(
List<VolunteerTotalRankingResponseDto> totalRanking,
List<VolunteerMonthlyRankingResponseDto> monthlyRanking,
List<VolunteerWeeklyRankingResponseDto> weeklyRanking){

return VolunteerRankingResponseDto.builder()
.volunteerTotalRankingResponse(totalRanking)
.volunteerMonthlyResponse(monthlyRanking)
.volunteerWeeklyRankingResponse(weeklyRanking)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.somemore.domains.volunteerrecord.dto.response;

import java.util.UUID;

public record VolunteerTotalRankingResponseDto(
UUID volunteerId,
int totalHours,
long ranking,
String nickname
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.somemore.domains.volunteerrecord.dto.response;

import java.util.UUID;

public record VolunteerWeeklyRankingResponseDto(
UUID volunteerId,
int totalHours,
long ranking,
String nickname
) {
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.somemore.domains.volunteerrecord.event.handler;

import com.somemore.domains.volunteerrecord.domain.VolunteerRecord;
import com.somemore.domains.volunteerrecord.usecase.VolunteerRecordCreateUseCase;
import com.somemore.domains.volunteerrecord.usecase.CreateVolunteerRecordUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -11,11 +11,11 @@
@Transactional
public class SettleVolunteerHoursHandlerImpl implements SettleVolunteerHoursHandler {

private final VolunteerRecordCreateUseCase volunteerRecordCreateUseCase;
private final CreateVolunteerRecordUseCase createvolunteerRecordUseCase;

@Override
public void handle(VolunteerRecord volunteerRecord) {

volunteerRecordCreateUseCase.create(volunteerRecord);
createvolunteerRecordUseCase.create(volunteerRecord);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.somemore.domains.volunteerrecord.repository;

import com.somemore.domains.volunteerrecord.dto.response.VolunteerMonthlyRankingResponseDto;
import com.somemore.domains.volunteerrecord.dto.response.VolunteerRankingResponseDto;
import com.somemore.domains.volunteerrecord.dto.response.VolunteerTotalRankingResponseDto;
import com.somemore.domains.volunteerrecord.dto.response.VolunteerWeeklyRankingResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.time.Duration;
import java.util.List;
import java.util.Optional;

@RequiredArgsConstructor
@Repository
public class VolunteerRankingRedisRepository {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인터페이스를 cacheRepo로 명명하고 redisRepo를 구현체로 두는 것은 어떨까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

말씀해주신 부분이 저희 컨벤션에 맞는거 같아요
곧 수정하겠습니다!


private final RedisTemplate<String, Object> redisTemplate;

private static final Duration CACHE_TTL = Duration.ofMinutes(60);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(끄덕)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(끄덕)

private static final String TOTAL_RANKING_KEY = "volunteer:total_ranking";
private static final String MONTHLY_RANKING_KEY = "volunteer:monthly_ranking";
private static final String WEEKLY_RANKING_KEY = "volunteer:weekly_ranking";

public void saveRanking(VolunteerRankingResponseDto rankings) {
redisTemplate.opsForValue().set(TOTAL_RANKING_KEY, rankings.volunteerTotalRankingResponse(), CACHE_TTL);
redisTemplate.opsForValue().set(MONTHLY_RANKING_KEY, rankings.volunteerMonthlyResponse(), CACHE_TTL);
redisTemplate.opsForValue().set(WEEKLY_RANKING_KEY, rankings.volunteerWeeklyRankingResponse(), CACHE_TTL);
}

@SuppressWarnings("unchecked")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어떤 오류가 있어서 설정하셨나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Json 직렬화시 나오는 무시해도 되는 경고 문구를 제거하려고 어노테이션을 추가했습니다!
혹시나 팀원분들이 로그 확인하실때 찜찜하실까봐 설정했습니다

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 확인했습니다~

public Optional<VolunteerRankingResponseDto> getRankings() {

List<VolunteerTotalRankingResponseDto> totalRanking =
(List<VolunteerTotalRankingResponseDto>) redisTemplate.opsForValue().get(TOTAL_RANKING_KEY);
List<VolunteerMonthlyRankingResponseDto> monthlyRanking =
(List<VolunteerMonthlyRankingResponseDto>) redisTemplate.opsForValue().get(MONTHLY_RANKING_KEY);
List<VolunteerWeeklyRankingResponseDto> weeklyRanking =
(List<VolunteerWeeklyRankingResponseDto>) redisTemplate.opsForValue().get(WEEKLY_RANKING_KEY);

if (totalRanking == null || monthlyRanking == null || weeklyRanking == null) {
return Optional.empty();
}
Comment on lines +42 to +44
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

하나라도 비어있으면 보내지 않으시는 이유가 있으신가요 ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프론트에서 탭으로 랭킹을 구분해서 보여주기때문에 월, 주간 같이 다른 탭을 클릭해야
볼 수 있는 랭킹의 경우 에러가 생겨도 발견이 늦을거 같다는 생각을 했습니다.
그래서 빠른 에러 파악을 위해 하나라도 문제가 생기면 빈 리스트를 반환하도록 했습니다

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러 해결법이 있겠지만 좋다고 생각합니다~ 확인했습니다


return Optional.of(VolunteerRankingResponseDto.of(
totalRanking,
monthlyRanking,
weeklyRanking
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,54 @@

import com.somemore.domains.volunteerrecord.domain.VolunteerRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface VolunteerRecordJpaRepository extends JpaRepository<VolunteerRecord, Long> {
}

@Query(value = """
SELECT volunteerId, totalHours, ranking
FROM (
SELECT
vr.volunteer_id AS volunteerId,
SUM(vr.volunteer_hours) AS totalHours,
DENSE_RANK() OVER (ORDER BY SUM(vr.volunteer_hours) DESC) AS ranking
FROM volunteer_record vr
GROUP BY vr.volunteer_id
) ranked
WHERE ranking <= 4
""", nativeQuery = true)
List<Object[]> findTotalTopRankingWithTies();
Comment on lines +11 to +23
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dense rank 와 같은 기능을 위해서 네이티브 쿼리를 활용하는 예시를 잘 확인했습니다!

혹시 일반적인 조회 기능정도의 역할을 데이터베이스에게 부여하고, 나머지는 자바로 처리하는 것은 어떤지 여쭤보고 싶습니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일반적인 조회 기능정도의 역할을 데이터베이스에게 부여
이 부분에 대해서도 고민을 했었는데요 결국 랭킹은 모든 데이터를 추합해서 계산을 해야하기 때문에
앱에서 처리를 진행할 시 결국 findAll을 해와야 한다는 문제가 있었습니다
데이터 수가 많아질 때 반드시 문제가 될 부분이라 생각해서 다른 방식을 생각했습니다.

DB에서 뷰 테이블을 만들고 뷰 테이블을 조회하는 방식도 생각을 했으나
공부가 더 필요한 부분이라 지금의 쿼리 방식을 선택하게 되었습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네, 맞습니다. 저는 "네이티브 쿼리를 사용하지 않는 방식"에 대해서도 고민해보았습니다.
예를 들어, 봉사 시간을 기준으로 상위 10명을 조회한 후, Java에서 추가적으로 순위를 매기고, 공동 순위를 고려해 4등까지의 데이터를 추출하는 방식입니다.
(10명을 가져왔을 떄, 공동 순위를 고려한 상황에서 5등이 정해지지 않는다면 10+N명 정도를 더 조회하는 방법((20+N)명이 조회된 상황)으로 진행할 수 있다고 생각했습니다.)

이 접근 방식은 일반적으로 충분히 효율적일 수 있지만, 최악의 경우, 예를 들어 공동 1등이 10,000명인 상황에서는 비효율적일 수 있다는 문제가 있습니다.
모든 상황을 고려했을 때, 데이터베이스에서 적절히 필터링된 데이터를 가져오는 현재의 네이티브 쿼리 방식이 더 적합할 것 같습니다.


@Query(value = """
SELECT volunteerId, totalHours, ranking
FROM (
SELECT
vr.volunteer_id AS volunteerId,
SUM(vr.volunteer_hours) AS totalHours,
DENSE_RANK() OVER (ORDER BY SUM(vr.volunteer_hours) DESC) AS ranking
FROM volunteer_record vr
WHERE YEARWEEK(vr.volunteer_date, 1) = YEARWEEK(CURDATE(), 1)
GROUP BY vr.volunteer_id
) ranked
WHERE ranking <= 4
""", nativeQuery = true)
List<Object[]> findWeeklyTopRankingWithTies();

@Query(value = """
SELECT volunteerId, totalHours, ranking
FROM (
SELECT
vr.volunteer_id AS volunteerId,
SUM(vr.volunteer_hours) AS totalHours,
DENSE_RANK() OVER (ORDER BY SUM(vr.volunteer_hours) DESC) AS ranking
FROM volunteer_record vr
WHERE MONTH(vr.volunteer_date) = MONTH(CURDATE())
AND YEAR(vr.volunteer_date) = YEAR(CURDATE())
GROUP BY vr.volunteer_id
) ranked
WHERE ranking <= 4
""", nativeQuery = true)
List<Object[]> findMonthlyTopRankingWithTies();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

import com.somemore.domains.volunteerrecord.domain.VolunteerRecord;

import java.util.List;

public interface VolunteerRecordRepository {
void save(VolunteerRecord volunteerRecord);
List<Object[]> findTotalTopRankingWithTies();
List<Object[]> findWeeklyTopRankingWithTies();
List<Object[]> findMonthlyTopRankingWithTies();
Comment on lines +9 to +11
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쿼리 결과 반환값을 명시적인 DTO로 지정할 수 없었는지 여쭤보고 싶습니다!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음엔 DTO 타입을 넣어줬으나
UUID 직렬화가 제대로 이루어지지 않아서 Object[]로 대체 해놓은 상태입니다!
TODO에 추가해서 더 나은 해결방법을 찾아보겠습니다

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 아무래도 레디스 직렬화가 설정이 애매한 부분이 많더라구요. 추후에 수정해도 될 것 같습니다~


}
Loading
Loading