En un proyecto web, usando los últimos datos de primavera (1.10.2) con una base de datos MySQL 5.6, estoy tratando de usar una consulta nativa con paginación pero estoy experimentando un org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException
error al inicio.
ACTUALIZACIÓN : 20180306 Este problema ahora se solucionó en Spring 2.0.4 Para aquellos que aún están interesados o estancados con versiones anteriores, consulte las respuestas y comentarios relacionados para encontrar soluciones.
De acuerdo con el Ejemplo 50 en Usar @Query de la documentación de datos de primavera, esto es posible especificando la consulta en sí y un countQuery, así:
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);
}
Por curiosidad, en NativeJpaQuery
clase puedo ver que contiene el siguiente código para verificar si es una consulta jpa válida:
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);
}
}
Mi consulta contiene un Pageable
parámetro, también lo hasPagingOrSortingParameter
es true
, pero también busca una secuencia #pageable
o #sort
dentro de queryString
, que no proporciono.
Intenté agregar #pageable
(es un comentario) al final de mi consulta, lo que hace que la validación pase, pero luego, falla en la ejecución y dice que la consulta espera un parámetro adicional: 3 en lugar de 2.
Lo curioso es que, si cambio manualmente containsPageableOrSortInQueryExpression
de false
a true
durante la ejecución, la consulta funciona bien, por lo que no sé por qué está verificando que esa cadena esté en mi queryString
y no sé cómo proporcionarla.
Cualquier ayuda será muy apreciada.
Actualización 30/01/2018 Parece que los desarrolladores del proyecto spring-data están trabajando en una solución para este problema con un PR de Jens Schauder
fuente
Respuestas:
Mis disculpas de antemano, esto resume bastante bien la pregunta original y el comentario de Janar , sin embargo ...
Me encuentro con el mismo problema: encontré el Ejemplo 50 de Spring Data como la solución para mi necesidad de tener una consulta nativa con paginación, pero Spring se quejaba al inicio de que no podía usar la paginación con consultas nativas.
Solo quería informar que logré ejecutar con éxito la consulta nativa que necesitaba, usando paginación, con el siguiente código:
@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);
El countQuery (que está comentado en el bloque de código) es necesario para usarlo
Page<Author>
como el tipo de retorno de la consulta, las nuevas líneas alrededor del comentario "#pageable" son necesarias para evitar el error de tiempo de ejecución en el número de parámetros esperados (solución alternativa del solución alterna). Espero que este error se solucione pronto ...fuente
?#{#pageable}
está funcionando en cambio\n#pageable\n
.:authorId
. Cambié tu\n#pageable\n
a--#pageable\n
por postgresql. El countQuery es necesario como sugirió ya que muchos ejemplos usan List <> en lugar de Page <> su respuesta fue acertada para esto. Revisé los mismos documentos y si no fuera por tu respuesta, simplemente me habría rendido./*:pageable*/
funciona (con SQL Server, Hibernate 5.4.1.Final y Spring Boot 2.2.1)Este es un truco para un programa que usa Spring Data JPA antes de la versión 2.0.4 .
El código ha funcionado con PostgreSQL y 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}
es paraPageable
.countQuery
es paraPage<User>
.fuente
spring.jpa.show-sql=false
deapplication.properties
; 2. establecer?#{#pageable}
en su nativeQuery y 3. analizar el resultado SQL del registro. @Lasneyx creó el problema DATAJPA-928 para esta peculiaridad de Spring Data JPA.Solo para el registro, usando H2 como base de datos de prueba y MySQL en tiempo de ejecución, este enfoque funciona (el ejemplo es el objeto más nuevo en el grupo ):
@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 Data JPA 1.10.5, H2 1.4.194, MySQL Community Server 5.7.11-log (innodb_version 5.7.11).
fuente
Tengo exactamente el mismo síntoma que @Lasneyx. Mi solución para la consulta nativa de 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);
fuente
Prueba esto:
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); }
(
"/* */"
paraOracle notation
)fuente
Utilizo la base de datos de Oracle y no obtuve el resultado, sino un error con la coma generada del que d-man habló anteriormente.
Entonces mi solución fue:
Pageable pageable = new PageRequest(current, rowCount);
Como puede ver sin orden al crear Pagable.
Y el método en el 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); }
fuente
Los dos enfoques siguientes funcionan bien con MySQL para paginar consultas nativas. Sin embargo, no funcionan con H2. Se quejará del error de sintaxis sql.
fuente
Usar "ORDER BY id DESC \ n-- #pageable \ n" en lugar de "ORDER BY id \ n # pageable \ n" funcionó para mí con MS SQL SERVER
fuente
Podría integrar con éxito la paginación en
como sigue.
@Query( value = “SELECT * FROM Users”, countQuery = “SELECT count(*) FROM Users”, nativeQuery = true) Page<User> findAllUsersWithPagination(Pageable pageable);
fuente
Funciona de la siguiente manera:
public interface UserRepository extends JpaRepository<User, Long> { @Query(value = "select * from (select (@rowid\\:=@rowid+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); }
fuente
Para mí a continuación trabajó en 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);
fuente
Estoy usando el siguiente código. trabajando
@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);
fuente
Eliminar \ n # pageable \ n tanto de la consulta como de la consulta de recuento funcionó para mí. Versión de Springboot: 2.1.5.RELEASE DB: Mysql
fuente
Esto funcionó para mí (estoy usando Postgres) en Groovy:
@RestResource(path="namespaceAndNameAndRawStateContainsMostRecentVersion", rel="namespaceAndNameAndRawStateContainsMostRecentVersion") @Query(nativeQuery=true, countQuery=""" SELECT COUNT(1) FROM ( SELECT ROW_NUMBER() OVER ( PARTITION BY name, provider_id, state ORDER BY version DESC) version_partition, * FROM mydb.mytable WHERE (name ILIKE ('%' || :name || '%') OR (:name = '')) AND (namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND (state = :state OR (:state = '')) ) t WHERE version_partition = 1 """, value=""" SELECT id, version, state, name, internal_name, namespace, provider_id, config, create_date, update_date FROM ( SELECT ROW_NUMBER() OVER ( PARTITION BY name, provider_id, state ORDER BY version DESC) version_partition, * FROM mydb.mytable WHERE (name ILIKE ('%' || :name || '%') OR (:name = '')) AND (namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND (state = :state OR (:state = '')) ) t WHERE version_partition = 1 /*#{#pageable}*/ """) public Page<Entity> findByNamespaceContainsAndNameContainsAndRawStateContainsMostRecentVersion(@Param("namespace")String namespace, @Param("name")String name, @Param("state")String state, Pageable pageable)
La clave aquí fue usar:
/*#{#pageable}*/
Me permite ordenar y paginar. Puedes probarlo usando algo como esto: http: // localhost: 8080 / api / v1 / entity / search / namespaceAndNameAndRawStateContainsMostRecentVersion? Namespace = & name = & state = Published & page = 0 & size = 3 & sort = name, desc
Tenga cuidado con este problema: Spring Pageable no traduce el nombre de @Column
fuente
Puede usar el siguiente código para h2 y MySQl
@Query(value = "SELECT req.CREATED_AT createdAt, req.CREATED_BY createdBy,req.APP_ID appId,req.NOTE_ID noteId,req.MODEL model FROM SUMBITED_REQUESTS req inner join NOTE note where req.NOTE_ID=note.ID and note.CREATED_BY= :userId " , countQuery = "SELECT count(*) FROM SUMBITED_REQUESTS req inner join NOTE note WHERE req.NOTE_ID=note.ID and note.CREATED_BY=:userId", nativeQuery = true) Page<UserRequestsDataMapper> getAllRequestForCreator(@Param("userId") String userId,Pageable pageable);
fuente
Reemplazar / #pageable / con? # {# Pageable} permite hacer paginación. Agregar PageableDefault le permite establecer el tamaño de los elementos de la página.
fuente