Fetch join + 페이징에선 CountQuery를 별도로 만들어 줘야한다!

박진형·2022년 1월 29일
1

JPA

목록 보기
5/7
post-custom-banner

오류

Spring Data Jpa에서 페이징을 위한 쿼리를 작성했는데 이 쿼리에서는 fetch join이 사용된다.
fetch join이 들어간 경우에는 CountQuery를 정상적으로 자동으로 만들어주지 못한다.
아마 그래서 발생하는 문제인 것같다.

Caused by: java.lang.IllegalArgumentException: 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=null,role=com.deu.football_love.domain.Post.board,tableName=board,tableAlias=board1_,origin=post post0_,columns={post0_.board_id,className=com.deu.football_love.domain.Board}}] [select count(p) FROM com.deu.football_love.domain.Post p JOIN FETCH p.board JOIN  p.board.team WHERE p.board.id = :boardId]
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:138)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:734)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:114)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362)
	at com.sun.proxy.$Proxy132.createQuery(Unknown Source)
	at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:87)
	... 139 more
Caused by: 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=null,role=com.deu.football_love.domain.Post.board,tableName=board,tableAlias=board1_,origin=post post0_,columns={post0_.board_id,className=com.deu.football_love.domain.Board}}] [select count(p) FROM com.deu.football_love.domain.Post p JOIN FETCH p.board JOIN  p.board.team WHERE p.board.id = :boardId]
	at org.hibernate.QueryException.generateQueryException(QueryException.java:120)
	at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:220)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
	at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
	at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:613)
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:725)
	... 147 more
Caused by: 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=null,role=com.deu.football_love.domain.Post.board,tableName=board,tableAlias=board1_,origin=post post0_,columns={post0_.board_id,className=com.deu.football_love.domain.Board}}]
	at org.hibernate.hql.internal.ast.tree.SelectClause.initializeExplicitSelectClause(SelectClause.java:215)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.useSelectClause(HqlSqlWalker.java:1028)
	at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:796)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:694)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:330)
	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:278)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
	... 153 more

해결 방법

@Query 어노테이션에는 countQuery를 직접 작성할 수 있다.
다음과 같이 countQuery를 직접 작성해준다.

  • before
@Query("SELECT p FROM Post p" +
            " JOIN FETCH p.board" +
            " JOIN  p.board.team" +
            " WHERE p.board.id = :boardId")
    Page<Post> selectAllPostsByBoardId(@Param("boardId") Long boardId, Pageable pageable);
  • after
@Query(value = "SELECT p FROM Post p" +
            " JOIN FETCH p.board" +
            " JOIN  p.board.team" +
            " WHERE p.board.id = :boardId",
        countQuery = "SELECT count(p) FROM Post p WHERE p.board.id = :boardId")
    Page<Post> selectAllPostsByBoardId(@Param("boardId") Long boardId, Pageable pageable);

CountQuery를 직접 작성하고 나니 실행이 잘 된다.

post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 1월 2일

덕분에 에러가 안 나네요 감사합니다

답글 달기