在一个Web项目中,使用最新的spring-data(1.10.2)和MySQL 5.6数据库,我正在尝试使用带有分页的本机查询,但我在启动时遇到org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException
。
根据Example 50 at Using @Query from spring-data documentation,可以指定查询本身和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
,但它也在{{1}内寻找#pageable
或#sort
个序列我没有提供。
我在我的查询结束时尝试添加queryString
(这是注释),这使得验证通过但是,它在执行时失败,说查询需要一个额外的参数:3而不是2
有趣的是,如果我在运行时手动将#pageable
从containsPageableOrSortInQueryExpression
更改为false
,则查询工作正常,因此我不知道为什么要检查该字符串是在true
,我不知道如何提供它。
非常感谢任何帮助。
更新01/30/2018 似乎spring-data项目的开发人员正在使用PR by Jens Schauder
来解决此问题答案 0 :(得分:32)
我提前道歉,这几乎总结了原始问题和Janar的评论,但是......
我遇到了同样的问题:我发现Example 50 of Spring Data是我需要使用分页的本机查询的解决方案,但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”注释的换行符以避免预期参数数量的运行时错误(变通方法的变通方法)。我希望这个bug很快就能解决......
答案 1 :(得分:20)
此代码与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<>
。
答案 2 :(得分:10)
仅仅是为了记录,在运行时使用H2作为测试数据库和MySQL,这种方法有效(例如newest object in 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);
Spring Data JPA 1.10.5,H2 1.4.194,MySQL Community Server 5.7.11-log(innodb_version 5.7.11)。
答案 3 :(得分:6)
我有与@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);
答案 4 :(得分: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);
}
("/* */"
的{{1}})
答案 5 :(得分:4)
我使用的是oracle数据库,但没有得到结果,而是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);
}
答案 6 :(得分:1)
以下两种方法都适用于MySQL以分页本机查询。但他们并没有与H2合作。它会抱怨sql语法错误。
答案 7 :(得分:1)
我可以成功地将分页集成到
spring-data-jpa-2.1.6
如下。
@Query(
value = “SELECT * FROM Users”,
countQuery = “SELECT count(*) FROM Users”,
nativeQuery = true)
Page<User> findAllUsersWithPagination(Pageable pageable);
答案 8 :(得分:0)
我添加这个答案只是作为那些使用更新版本 Spring Boot 的用户的占位符。在 Spring Boot 2.4.3 上,我发现不需要任何解决方法,以下代码直接为我工作:
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value="SELECT * FROM USERS WHERE LASTNAME = ?1", nativeQuery=true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
countQuery
定义不是必需的,实际上对 Page#getTotalElements()
的调用已经返回了正确的计数,正如 JPA 自己的内部计数查询所返回的那样。
上面的代码非常强大,提供了通过本机查询进行的分页,但将结果返回到实际的 Java 实体中(而不是丑陋而笨重的 List<Object[]>
,这有时是必要的)。
答案 9 :(得分:0)
您可以使用以下代码来实现,
@Query(value = "SELECT * FROM users u WHERE ORDER BY ?#{#pageable}", nativeQuery = true)
List<User> getUsers(String name, Pageable pageable);
只需使用 ORDER BY ?#{#pageable} 并将页面请求传递给您的方法。
享受吧!
答案 10 :(得分:0)
您可以将以下代码用于h2和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);
答案 11 :(得分:0)
这在Groovy中对我(我正在使用Postgres)起作用:
@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)
此处的关键是使用:/*#{#pageable}*/
它允许我进行排序和分页。 您可以使用以下命令进行测试:http://localhost:8080/api/v1/entities/search/namespaceAndNameAndRawStateContainsMostRecentVersion?namespace=&name=&state=published&page=0&size=3&sort=name,desc
答案 12 :(得分:0)
从查询和计数查询中删除\ n#pageable \ n都对我有用。 Springboot版本:2.1.5.RELEASE DB:Mysql
答案 13 :(得分:0)
我正在使用以下代码。工作
@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);
答案 14 :(得分:0)
下面对我来说,我在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);
答案 15 :(得分:0)
使用&#34; ORDER BY id DESC \ n-- #pageable \ n&#34; 而不是&#34; ORDER BY id \ n#pageable \ n&#34;用MS SQL SERVER为我工作
答案 16 :(得分:0)
确实如下:
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);
}
答案 17 :(得分:-1)
/ #pageable /允许分页。 添加PageableDefault允许您设置页面元素的大小。