토이 프로젝트를 진행 하던중, dsl에서 subquery를 사용할 일이 생겼다.
내가 구축한 DB ERD는

위 사진과 같은데 이중 vote와 posting의 관계에 있어서 문제가 있었다.
좋아요의 경우 vote.liked에 1
싫어요의 경우 vote.liked에 -1 이 들어가는 모델을 생각하고 DB를 구현 했었는데,
좋아요 개수로 where 절에 제약을 만드는 경우는 subquery가 정상적으로 작동했다.
private BooleanExpression filterByLikes(Integer likes) {
if (likes == null) {
return null;
}
return JPAExpressions
.select(vote.count())
.from(vote)
.where(vote.posting.eq(posting).and(vote.like.eq(1)))
.goe(Long.valueOf(likes));
}
하지만 문제는 다른 곳 에서 발생했다.
select p.* from posting p left outer join vote v on p.pk =v.posting group by p.pk order by (select count(*) from vote v2 where v2.posting =p.pk and v2.liked =1 ) desc ;
위 query와 같이 포스팅 중 vote의 like가1 인 경우가 많은 순으로 정렬 하려 했다.
하지만 dsl에서 코드를 작성하던 중 , OrderSpecifier 에서는 subquery를 사용 할수 없다는 것을 알았다.
시간순으로 말해보겠다.
이틀동안 OrderSpecifier 어떻게든 subquery를 사용하려 애썻다.
처음에는 가볍게
return new OrderSpecifier<>(Order.DESC,vote.like.eq(1).count());
이렇게 하면 될줄 알았다.
하지만 쿼리는
order by count(vote.like = ?2) desc
으로 나가고 있었고, subquery로 작성하기 위해
QVote vote2 = new QVote("v2");
JPQLQuery<Long> subquery = JPAExpressions.select(vote2.count())
.from(vote2)
.where(vote2.posting.eq(posting), vote2.like.eq(1));
return new OrderSpecifier<>(Order.DESC, subquery);
JPQLQuery를 이용해 쿼리를 만든 후 OrderSpecifier 에 넣어보았지만,
order by (select count(v2)
from com.cutegyuseok.freetalk.posting.entity.Vote v2
where v2.posting = posting and v2.like = ?2) desc
쿼리가 제대로 나가는 것 처럼 보였지만\
NoViableAltException: unexpected AST node: query
오류가 났다.
쿼리가 올바르게 작성되지 않았거나 데이터가 옳바르지 않을때 생기는 오류인 것으로 알고있다.
다른 여러가지 시도도 정말 많이 해봤다.
그러던중 곰곰히 생각해보니, 내게 필요한 것은 좋아요의 수만 필요하고, 싫어요의 경우 보여지는 경우에 반영이 되지 않아도 되었다.
싫어요가 -1이였기 때문에 sum을 사용하지 않고 서브쿼리로 count 하였던 것인데 0을 사용하면 sum을 사용해도 된다.
따라서 좋아요 기능의 방식을 좋아요는 1 싫어요는 0 으로 바꾸어 적용하고 sum을 이용해
case "LIKES":
return new OrderSpecifier<>(Order.DESC, vote.like.sum());
으로 구현하였더니 정상적으로 작동하였다.
'Spring & SpringBoot' 카테고리의 다른 글
| JPA SQL 오류 경험 (0) | 2023.02.05 |
|---|---|
| HashTag 검색 SQL 구현해보기 (0) | 2023.01.27 |
| Spring security 시작하기 (0) | 2023.01.20 |
| MockMVC (0) | 2023.01.13 |
| SpringBoot JPA 사용하기 (0) | 2022.12.30 |