문제코드
아래와 같은 Query로 유저가 러닝 활동을 하였을 때 얻은 뱃지를 조회하려고 하였다. 하지만 실제 데이터는 아래의 JSON데이터 획득한 뱃지가 없는 경우에도 모든 러닝 활동에 뱃지가 생겼다.
public List<RunRecord> findTop3ByUserIdOrderByCreatedAtJoinBadgeAchv(Integer userId) {
Query query = em.createQuery("select r from RunRecord r left outer join fetch runBadgeAchvs rba where r.user.id = : userId order by r.createdAt desc", RunRecord.class);
query.setParameter("userId", userId);
query.setMaxResults(3);
List<RunRecord> recentRuns = query.getResultList();
return recentRuns;
}
[
{
"id": 15,
"title": "트레일 러닝 14",
"totalDistanceMeters": 1800,
"totalDurationSeconds": 630,
"avgPace": 350,
"createdAt": "2025-06-23 00:00:00",
"badges": [
{
"id": 1,
"name": "첫 시작",
"imageUrl": "https://example.com/badges/first_run.png"
}
]
},
{
"id": 14,
"title": "6월 러닝 13",
"totalDistanceMeters": 1700,
"totalDurationSeconds": 600,
"avgPace": 352,
"createdAt": "2025-06-22 00:00:00",
"badges": [
{
"id": 1,
"name": "첫 시작",
"imageUrl": "https://example.com/badges/first_run.png"
}
]
}
]
해결
이유는 엔티티에서
runBadgeAchvs
가 Relation 설정이 되어 있는데 문제의 코드에서는 runBadgeAchvs
엔티티를 조회해 왔기 때문에 유저가 획득한 모든 뱃지를 해당 러닝 기록에 넣었다. 그래서 해결 한 방법은 Query에서 RunRecord
안에 있는 runBadgeAchvs
를 join 하여서 해결 하였다. @OneToMany(mappedBy = "runRecord", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<RunBadgeAchv> runBadgeAchvs = new ArrayList<>(); // 자식 뱃지들
public List<RunRecord> findTop3ByUserIdOrderByCreatedAtJoinBadgeAchv(Integer userId) {
Query query = em.createQuery("select r from RunRecord r left outer join fetch r.runBadgeAchvs rba where r.user.id = : userId order by r.createdAt desc", RunRecord.class);
query.setParameter("userId", userId);
query.setMaxResults(3);
List<RunRecord> recentRuns = query.getResultList();
return recentRuns;
}
[
{
"id": 15,
"title": "트레일 러닝 14",
"totalDistanceMeters": 1800,
"totalDurationSeconds": 630,
"avgPace": 350,
"createdAt": "2025-06-23 00:00:00",
"badges": [
{
"id": 1,
"name": "첫 시작",
"imageUrl": "https://example.com/badges/first_run.png"
}
]
},
{
"id": 14,
"title": "6월 러닝 13",
"totalDistanceMeters": 1700,
"totalDurationSeconds": 600,
"avgPace": 352,
"createdAt": "2025-06-22 00:00:00",
"badges": []
}
]
Share article