Подтвердить что ты не робот

Spring Данные и исходный запрос с разбивкой на страницы

В веб-проекте, используя последние данные о Spring (1.10.2) с базой данных MySQL 5.6, я пытаюсь использовать собственный запрос с разбиением на страницы, но я испытываю org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException при запуске.

ОБНОВЛЕНИЕ: 20180306 Эта проблема теперь исправлена в Spring 2.0.4. Для тех, кто все еще заинтересован или застрял в старых версиях, проверьте соответствующие ответы и комментарии для обходных путей.

В соответствии с примером 50 в разделе "Использование @Query" из документации по данным о Spring это возможно с указанием самого запроса и 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, поэтому hasPagingOrSortingParameter имеет значение true, но он также ищет последовательность #pageable или #sort внутри queryString, которую я не предоставляю.

Я попытался добавить #pageable (это комментарий) в конце моего запроса, что делает проверку #pageable но затем происходит сбой при выполнении, говоря, что запрос ожидает один дополнительный параметр: 3 вместо 2.

Забавно то, что, если я вручную изменяю containsPageableOrSortInQueryExpression с false на true во время выполнения, запрос работает нормально, поэтому я не знаю, почему он проверяет наличие этой строки в моем queryString и я не знаю, как ее предоставить.

Любая помощь приветствуется.

Обновление от 30.01.2008 Похоже, что разработчики проекта spring-data работают над исправлением этой проблемы с пиаром Jens Schauder.

4b9b3361

Ответ 1

Мои извинения заранее, это в значительной степени суммирует исходный вопрос и комментарий от Janar, однако...

Я столкнулся с той же проблемой: я нашел Пример 50 Spring Данные в качестве решения для моей потребности в нативном запросе с pagination, но 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);

Для использования Page<Author> требуется countQuery (который закомментирован в блоке кода) как возвращаемый тип запроса, новые строки вокруг комментария "#pageable" необходимы, чтобы избежать ошибки времени выполнения для числа ожидаемых параметров (обходной путь обходного пути). Я надеюсь, что эта ошибка скоро будет исправлена ​​...

Ответ 2

Этот код работает с 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<>.

Ответ 3

Только для записи, используя H2 в качестве тестовой базы данных и MySQL во время выполнения, этот подход работает (например, новейший объект в группе):

@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);

Spring Данные JPA 1.10.5, H2 1.4.194, Сервер сообщества MySQL 5.7.11-log (innodb_version 5.7.11).

Ответ 4

У меня такой же симптом, как @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);

Ответ 5

Попробуйте следующее:

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)

Ответ 6

Я использую базу данных оракула, и я получил не результат, а ошибку с сгенерированной запятой, о которой 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);
 }

Ответ 7

Оба следующих подхода отлично работают с MySQL для разбиения на страницы собственного запроса. Однако они не работают с H2. Он будет жаловаться на синтаксическую ошибку sql.

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

Ответ 8

Использование "ORDER BY id DESC\n-- #pageable\n" вместо "ORDER BY id\n # pageable\n" работал у меня с MS SQL SERVER

Ответ 9

Он работает следующим образом:

public interface UserRepository extends JpaRepository<User, Long> {
    @Query(value = "select * from (select (@rowid\\:[email protected]+1) as RN, u.* from USERS u, (SELECT @rowid\\:=0) as init where  LASTNAME = ?1) as total"+
        "where RN between ?#{#pageable.offset-1} and ?#{#pageable.offset + #pageable.pageSize}",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
    Page<User> findByLastname(String lastname, Pageable pageable);
}

Ответ 10

@EmanueleFusco

ТЫ БОГ!

Я бил головой об этом около 8 долгих часов и не мог понять, что это было.

Я получал эту ошибку в строке 4 рядом с WHERE

MySQLSyntaxErrorException: у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с WHERE) FROM building_institutions WHERE building_institutions.building_id = 1) A 'в строке 2

когда мой запрос выглядит так:

@Query(
        value = "SELECT username, password, description, location, title, user_id FROM (institution INNER JOIN user ON institution.user_id = user.id) LEFT JOIN\n" +
                "(SELECT * FROM building_institutions WHERE building_institutions.building_id = 1) AS reserved_institutions\n" +
                "ON reserved_institutions.institutions_user_id = kits_nwt.institution.user_id\n" +
                "WHERE reserved_institutions.institutions_user_id IS null ORDER BY ?#{#pageable}",
        nativeQuery = true)
Page<Institution> findPotentialInstitutionsByBuildingId(Long userId, Pageable pageable);

Но ошибка была там, потому что я не добавлял параметр countQuery в аннотацию @Query.

Отметьте мой вопрос SO, который я попросил получить LEFT JOIN SQL-запрос. Там я ответил на свой вопрос и написал код, который работает для моего сложного запроса.

Приветствия:)

Ответ 11

У меня ниже работал в MS SQL

 @Query(value="SELECT * FROM ABC r where r.type in :type  ORDER BY RAND() \n-- #pageable\n ",nativeQuery = true)
List<ABC> findByBinUseFAndRgtnType(@Param("type") List<Byte>type,Pageable pageable);

Ответ 12

Я использую код ниже. работая

@Query(value = "select * from user usr" +
  "left join apl apl on usr.user_id = apl.id" +
  "left join lang on lang.role_id = usr.role_id" +
  "where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds ORDER BY ?#{#pageable}",
  countQuery = "select count(*) from user usr" +
      "left join apl apl on usr.user_id = apl.id" +
      "left join lang on lang.role_id = usr.role_id" +
      "where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds",
  nativeQuery = true)
Page<AplUserEntity> searchUser(@Param("scrname") String scrname,@Param("uname") String  uname,@Param("roleIds") List<Long> roleIds,Pageable pageable);

Ответ 13

Замена /# pageable/на? # {# Pageable} позволяет выполнять нумерацию страниц. Добавление PageableDefault позволит вам установить размер элементов страницы.