본문 바로가기
내가 배운 것들/문제 해결

[QueryDSL] 에러 발생 - query specified join fetching, but the owner of the fetched association was not present in the select list

by Zabee52 2022. 1. 1.

QueryDSL

발생 에러

org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
[FromElement
{
  explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=
  board,role=com.teamproj.backend.model.board.BoardLike.board,
  tableName=board,tableAlias=board1_,
  origin=board_like boardlike0_,
  columns={boardlike0_.board_board_id,
           className=com.teamproj.backend.model.board.Board
  }
}
]

select board.boardId, board.thumbNail, board.title, user.nickname, count(boardLike.board) as c
  from com.teamproj.backend.model.board.BoardLike boardLike
  left join fetch boardLike.board as board
  left join fetch boardLike.user as user
 where board.boardCategory = ?1
   and boardLike.createdAt between ?2
   and ?3
 group by boardLike.board
 order by c desc

인용문은 복사 붙여넣기 할 때 엔터가 적용이 안 돼서 자바 코드블럭으로 올리는 점 양해 바란다..... 티스토리 조금 나를 서운하게 하네?

 

에러 발생 코드

private List<Tuple> getYesterdayLikeCountRankTuple(BoardCategory boardCategory, int count) {
    QBoardLike qBoardLike = QBoardLike.boardLike;
    QBoard qBoard = QBoard.board;
    QUser qUser = QUser.user;

    LocalDateTime startDatetime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.of(0, 0, 0)); //어제 00:00:00
    LocalDateTime endDatetime = LocalDateTime.of(LocalDate.now(), LocalTime.of(23, 59, 59)); //오늘 23:59:59
    NumberPath<Long> likeCnt = Expressions.numberPath(Long.class, "c");

    return queryFactory.select(qBoard.boardId, qBoard.thumbNail, qBoard.title, qUser.nickname, qBoardLike.board.count().as(likeCnt))
            .from(qBoardLike)
            .leftJoin(qBoardLike.board, qBoard)
            .fetchJoin()
            .leftJoin(qBoardLike.user, qUser)
            .fetchJoin()
            .where(qBoard.boardCategory.eq(boardCategory)
                    .and(qBoardLike.createdAt.between(startDatetime, endDatetime)))
            .groupBy(qBoardLike.board)
            .orderBy(likeCnt.desc())
            .limit(count)
            .fetch();
}

 

에러 발생 이유 : DTO 형식의 반환형에 fetchJoin()을 실시하여 발생

문제 해결 : fetchJoin()을 제거하여 해결.

 

private List<Tuple> getYesterdayLikeCountRankTuple(BoardCategory boardCategory, int count) {
        QBoardLike qBoardLike = QBoardLike.boardLike;
        QBoard qBoard = QBoard.board;
        QUser qUser = QUser.user;

        LocalDateTime startDatetime = LocalDateTime.of(LocalDate.now().minusDays(1), LocalTime.of(0, 0, 0)); //어제 00:00:00
        LocalDateTime endDatetime = LocalDateTime.of(LocalDate.now(), LocalTime.of(23, 59, 59)); //오늘 23:59:59
        NumberPath<Long> likeCnt = Expressions.numberPath(Long.class, "c");

        return queryFactory.select(qBoard.boardId, qBoard.thumbNail, qBoard.title, qUser.nickname, qBoardLike.board.count().as(likeCnt))
                .from(qBoardLike)
                .leftJoin(qBoardLike.board, qBoard)
              //.fetchJoin()
                .leftJoin(qBoardLike.user, qUser)
              //.fetchJoin()
                .where(qBoard.boardCategory.eq(boardCategory)
                        .and(qBoardLike.createdAt.between(startDatetime, endDatetime)))
                .groupBy(qBoardLike.board)
                .orderBy(likeCnt.desc())
                .limit(count)
                .fetch();
    }

근데, 문제를 이 방식으로 해결했을 때 남는 잠재적 위험성이 하나 있다. fetchJoin을 실시하지 않을 시 N+1 문제에서 자유로울 수 없다는 점이다. 현재의 경우 추가적인 조회 수요가 발생하지 않는 작업이기 때문에 이렇게 해결을 해도 상관은 없지만, 항상 적용할 수 있는 솔루션은 아니라는 점을 명심해야 할 것이다.

 

 

 

N+1 문제까지 해결한 문제에 대한 StackOverFlow 글이 있는 것 같다.(아직 해석은 안 해봤다)

혹시 N+1 문제도 해결하고 싶다면 아래 링크를 한 번 읽어보는 것을 추천한다. 나도 아직 해석은 안 해봐서 명쾌한 해답이 되는지는 잘 모르겠다.

 

query specified join fetching, but the owner of the fetched association was not present in the select list

I'm selecting two id columns but get error specified: org.hibernate.QueryException: **query specified join fetching, but the owner of the fetched association was not present in the select list** [

stackoverflow.com

 

댓글