如何对Spring Data进行分页?

时间:2018-06-05 10:08:25

标签: spring spring-data spring-data-jpa

我有一个后端应用,我需要查询元素列表,然后返回Page而不是List of Stream。我想知道我的分页是否正常(因为我在POSTMAN上测试时出错)。 Tihis是我的代码除以层......

这是我的控制器

@GetMapping(value = "/findAll/{page]/{count}")
    //@PreAuthorize("hasAnyRole('NORMALUSER')")
    public ResponseEntity<Response<Page<Gasto>>> findAllByCurrentUser(HttpServletRequest request, 
            @RequestBody Gasto gasto, 
            @PathVariable int page,
            @PathVariable int count) {
        Response<Page<Gasto>> response = new Response<>();
        Page<Gasto> gastos = null;

        User userRequest = userFromRequest(request);
        gastos = gastosService.findAllByCurrentUser(userRequest.getId(), page, count);
        response.setData(gastos);
        return ResponseEntity.ok(response);
    }

这是我的服务类

@Override
    public Page<Gasto> findAllByCurrentUser(Long userId,int page, int count) {
        Pageable pages =  new PageRequest(page, count);
        return gastoRepository.findAllByCurrentUser(userId,pages);
    }

这是我的JPA存储库

@Query(
        value = "FROM Gasto g where g.user.id = :userId order by g.id \n#pageable\n",
        countQuery = "SELECT COUNT(g) FROM Gasto g WHERE where g.user.id = :userId",
        nativeQuery = true 

        )
Page<Gasto> findAllByCurrentUser(@Param("userId") Long userId,Pageable pageable);

这是我在POSTMAN中的错误

{
    "timestamp": 1528154349243,
    "status": 404,
    "error": "Not Found",
    "message": "No message available",
    "path": "/ExpApp/api/gastos/fin"
}

这是我的错误:

Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.getResultSet(Loader.java:2117) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1900) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1876) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.doQuery(Loader.java:919) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2617) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.doList(Loader.java:2600) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2429) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.Loader.list(Loader.java:2424) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:336) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1967) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:322) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:483) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution$PagedExecution.doExecute(JpaQueryExecution.java:190) ~[spring-data-jpa-1.11.12.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:89) ~[spring-data-jpa-1.11.12.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:128) ~[spring-data-jpa-1.11.12.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:118) ~[spring-data-jpa-1.11.12.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:494) ~[spring-data-commons-1.13.12.RELEASE.jar:na]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:477) ~[spring-data-commons-1.13.12.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56) ~[spring-data-commons-1.13.12.RELEASE.jar:na]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) ~[spring-tx-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.3.17.RELEASE.jar:4.3.17.RELEASE]
    ... 120 common frames omitted
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM Gasto g where g.user.id = 2 order by g.id 
#pageable

1 个答案:

答案 0 :(得分:0)

修改:

您的查询确实不是有效的SQL查询。你的值中缺少“SELECT *”,你的countQuery中有一个双“where”。应该是:

@Query(
        value = "SELECT * FROM Gasto g where g.user.id = :userId order by g.id \n#pageable\n",
        countQuery = "SELECT COUNT(g) FROM Gasto g WHERE g.user.id = :userId",
        nativeQuery = true 
        )
Page<Gasto> findAllByCurrentUser(@Param("userId") Long userId,Pageable pageable);

由于它是原生SQL,我也对“g.user.id”持怀疑态度,但我会将其留给你的模型。

我设法在Spring Boot 1.5.13.RELEASE和2.0.2.RELEASE上用一个简单的例子重现了这个用例,#pageable只在Spring Boot 2之前是必需的,它正确地返回{{1适当的内容。

Page

@Query(
        value = "SELECT * FROM test t where t.id = ?1 order by t.id \n#pageable\n",
        countQuery = "SELECT COUNT(t.id) FROM test t WHERE t.id = ?1",
        nativeQuery = true
)
Page<Test> findNativeWithPageable(Long id, Pageable pageable);

Spring 2.X现在有一个测试来确保可分页的本机查询按预期工作: https://github.com/spring-projects/spring-data-jpa/commit/68efc510dfcd1c5a7df76b7c8bac4a7198471158

该文档似乎表明@Entity public class Test { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; //getters/setters } 不是必需的,如果没有它,它会如何表现?

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#_native_queries

#pageable

关于SO的另一个问题有一些解决方法:

Spring Data and Native Query with pagination