记一个Spring Data JPA自定义分页查询BUG

官方给出的自定义分页查询的示例是这样的:

1
2
3
4
5
6
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);
}

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query

然后实际执行时报错:

1
org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodException

这是因为在使用NativeQuery时,会有这样一个验证:

1
2
3
4
5
6
7
8
9
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或者Sort时,SQL语句中必须包含

1
2
#pageable
#sort

参考了众多解决方案都无效。例如

1
2
?#{#pageable}
\n#pageable\

https://stackoverflow.com/questions/38349930/spring-data-and-native-query-with-pagination

最终发现,其实只需要将#pageable合理的作为注释包含在SQL里即可。
我使用的Mysql,最终解决方案为:

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

我使用的是Spring boot 1.5.4,在新版本中应该此问题已经被修复了。

记一个Spring Data JPA自定义分页查询BUG

https://jingzhouzhao.github.io/archives/de80e1f4.html

作者

太阳当空赵先生

发布于

2019-06-18

更新于

2022-02-22

许可协议

评论