Как я могу сделать нумерацию страниц с Spring Data? - PullRequest
0 голосов
/ 05 июня 2018

У меня есть приложение для бэкэнда, в котором мне нужно запросить список элементов, и я возвращаю страницу вместо списка «Поток».Я хочу знать, хорошо ли я делаю пагинацию (потому что у меня ошибка при тестировании на 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 голосов
/ 05 июня 2018

Редактировать:

Ваш запрос действительно не является допустимым SQL.Вам не хватает «SELECT *» в вашем значении, и у вас есть двойное «где» в вашем countQuery.Должно быть:

@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 и правильно возвращает 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);

и

@Entity
public class Test {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
//getters/setters
}

В Spring 2.X теперь есть тест для проверки работоспособности встроенных запросов на странице: https://github.com/spring-projects/spring-data-jpa/commit/68efc510dfcd1c5a7df76b7c8bac4a7198471158


Документ, кажется, указывает, что #pageable не требуется, как он ведет себя без него?

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

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

Естьеще один вопрос по SO с несколькими обходными путями:

Spring Data и собственный запрос с разбиением на страницы

...