[spring] 페이지 매김을 사용한 스프링 데이터 및 네이티브 쿼리

웹 프로젝트에서 MySQL 5.6 데이터베이스와 함께 최신 스프링 데이터 (1.10.2)를 사용하여 페이지 매김과 함께 네이티브 쿼리를 사용하려고하지만 org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException시작할 때 발생합니다.

업데이트 : 20180306이 문제는 이제 Spring 2.0.4 에서 수정되었습니다. 여전히 이전 버전에 관심이 있거나 이전 버전을 사용하는 경우 관련 답변과 주석에서 해결 방법을 확인하십시오.

Spring-data 문서에서 @Query 사용의 Example 50에 따르면 다음 과 같이 쿼리 자체와 countQuery를 지정할 수 있습니다.

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
}

호기심으로 NativeJpaQuery수업 중에 유효한 jpa 쿼리인지 확인하는 다음 코드가 포함되어 있음을 알 수 있습니다.

public NativeJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, EvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
   super(method, em, queryString, evaluationContextProvider, parser);
   JpaParameters parameters = method.getParameters();
   boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
   boolean containsPageableOrSortInQueryExpression = queryString.contains("#pageable") || queryString.contains("#sort");
   if(hasPagingOrSortingParameter && !containsPageableOrSortInQueryExpression) {
       throw new InvalidJpaQueryMethodException("Cannot use native queries with dynamic sorting and/or pagination in method " + method);
   }
}

내 쿼리에는 Pageable매개 변수 가 포함되어 있으므로 hasPagingOrSortingParametertrue있지만 제공하지 않는 에서 #pageable또는 #sort시퀀스를 찾고 queryString있습니다.

#pageable쿼리 끝에 (주석)을 추가하여 유효성 검사를 통과했지만 쿼리에 2 대신 3이라는 추가 매개 변수가 필요하다는 메시지가 실행에 실패합니다.

재미있는 점은 실행 중에 수동으로 containsPageableOrSortInQueryExpression에서 false로 변경 true하면 쿼리가 제대로 작동하므로 해당 문자열이 내 위치에 있는지 확인하는 이유를 queryString모르고 제공하는 방법을 모릅니다.

어떤 도움이라도 대단히 감사하겠습니다.

2018
년 1 월 30업데이트 Spring-Data 프로젝트의 개발자 가 Jens SchauderPR 을 통해이 문제에 대한 수정 작업을하고있는 것 같습니다.



답변

미리 사과드립니다. 이것은 원래 질문과 Janar 의 의견을 거의 요약 한 것입니다 .

나는 같은 문제에 부딪혔다. 나는 SpringData의 Example 50을 페이지 매김이있는 네이티브 쿼리를 필요로하는 솔루션으로 찾았 지만 Spring은 시작할 때 네이티브 쿼리와 함께 페이지 매김을 사용할 수 없다고 불평했다.

다음 코드를 사용하여 페이지 매김을 사용하여 필요한 기본 쿼리를 성공적으로 실행했다고보고하고 싶었습니다.

    @Query(value="SELECT a.* "
            + "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
            + "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time)"
            + "ORDER BY a.id \n#pageable\n", 
        /*countQuery="SELECT count(a.*) "
            + "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
            + "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time) \n#pageable\n",*/
        nativeQuery=true)
public List<Author> findAuthorsUpdatedAndNew(Pageable pageable);

countQuery (코드 블록에서 주석 처리됨)는 Page<Author>
쿼리의 반환 유형으로 사용하는 데 필요하며, 예상 매개 변수 수에 대한 런타임 오류를 방지하기 위해 “#pageable”주석 주위에 줄 바꿈이 필요합니다 ( 해결 방법). 이 버그가 곧 수정되기를 바랍니다.


답변

이것은 버전 2.0.4 이전의 SpringData JPA를 사용하는 프로그램에 대한 해킹입니다 .

코드는 PostgreSQL 및 MySQL과 함께 작동합니다.

public interface UserRepository extends JpaRepository<User, Long> {

@Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY ?#{#pageable}",
       countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
       nativeQuery = true)
   Page<User> findByLastname(String lastname, Pageable pageable);
}

ORDER BY ?#{#pageable}입니다 Pageable.
countQuery입니다 Page<User>.


답변

기록을 위해 H2를 테스트 데이터베이스로 사용하고 MySQL을 런타임에 사용하면이 접근 방식이 작동합니다 (예는 group의 최신 객체 임 ).

@Query(value = "SELECT t.* FROM t LEFT JOIN t AS t_newer " +
        "ON t.object_id = t_newer.object_id AND t.id < t_newer.id AND o_newer.user_id IN (:user_ids) " +
        "WHERE t_newer.id IS NULL AND t.user_id IN (:user_ids) " +
        "ORDER BY t.id DESC \n-- #pageable\n",
        countQuery = "SELECT COUNT(1) FROM t WHERE t.user_id IN (:user_ids) GROUP BY t.object_id, t.user_id",
        nativeQuery = true)
Page<T> findByUserIdInGroupByObjectId(@Param("user_ids") Set<Integer> userIds, Pageable pageable);

SpringData JPA 1.10.5, H2 1.4.194, MySQL Community Server 5.7.11-log (innodb_version 5.7.11).


답변

@Lasneyx와 똑같은 증상이 있습니다. Postgres 네이티브 쿼리에 대한 해결 방법

@Query(value = "select * from users where user_type in (:userTypes) and user_context='abc'--#pageable\n", nativeQuery = true)
List<User> getUsersByTypes(@Param("userTypes") List<String> userTypes, Pageable pageable);


답변

이 시도:

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY /*#pageable*/",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
}

( "/* */"Oracle notation)


답변

나는 오라클 데이터베이스를 사용하고 결과를 얻지 못했지만 d-man이 위에서 말한 생성 된 쉼표로 오류가 발생했습니다.

그런 다음 내 해결책은 다음과 같습니다.

Pageable pageable = new PageRequest(current, rowCount);

Pagable을 만들 때 순서없이 볼 수 있습니다.

그리고 DAO의 방법 :

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 /*#pageable*/ ORDER BY LASTNAME",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
 }


답변

다음 두 가지 방법 모두 네이티브 쿼리 페이지 매김을 위해 MySQL에서 잘 작동합니다. 그래도 H2에서는 작동하지 않습니다. SQL 구문 오류를 표시합니다.

  • ORDER BY? # {# pageable}
  • a.id로 정렬 \ n # pageable \ n