Spring Data - 为什么不能使用本机查询进行分页

vto*_*tor 13 java spring spring-data-jpa

假设我们有一个名为的实体MyEntity.可以使用@Query和使用命名查询来查询可分页结果,例如

 @Query(value = "select e from MyEntity e where e.enabled = true")
 Page<MyEntity> findAllEnabled(Pageable pageable);
Run Code Online (Sandbox Code Playgroud)

但是,使用本机查询不可能实现相同的功能,所以这一点

 @Query(value = "select * from my_entity where enabled = true", nativeQuery = true)
 Page<MyEntity> findAllEnabled(Pageable pageable);
Run Code Online (Sandbox Code Playgroud)

不行.

这背后的原因是什么?是否可以使Pageable使用本机查询?

Mic*_*ons 32

我不知道这是否仍与您相关:至少在Spring Data JPA 1.9.4中,您可以指定两个查询.

给定一个存储库:

interface FoobarEntityRepository extends JpaRepository<FoobarEntity, Integer> {
    Page findFoobarsSpecialQuery(String someParameter, final Pageable pageable);
}
Run Code Online (Sandbox Code Playgroud)

您可以向实体添加2个本机查询,一个用于查询本身,另一个用于count语句:

@Entity
@SqlResultSetMappings({
    @SqlResultSetMapping(name = "SqlResultSetMapping.count", columns = @ColumnResult(name = "cnt"))
})
@NamedNativeQueries({
    @NamedNativeQuery(
            name = "FoobarEntity.findFoobarsSpecialQuery",
            resultClass = DailyPictureEntity.class,
            query = "Select * from foobars f where someValue = :someParameter "
    ),
    @NamedNativeQuery(
            name = "FoobarEntity.findFoobarsSpecialQuery.count",
            resultSetMapping = "SqlResultSetMapping.count",
            query = "Select count(*) as cnt from foobars f where someValue = :someParameter "
    )
})
FoobarEntity {
}
Run Code Online (Sandbox Code Playgroud)

诀窍是使用后缀指定计数查询.count.这也适用于Spring Data @Query注释.

请注意,您需要为计数查询提供SQL结果集映射.

这实际上很不错.


mav*_*azy 12

这是描述,在spring data jpa文档中给出(http://docs.spring.io/spring-data/jpa/docs/1.8.0.M1/reference/html/)

本机查询@Query注释允许通过将nativeQuery标志设置为true来执行本机查询.请注意,我们当前不支持对本机查询执行分页或动态排序,因为我们必须操纵声明的实际查询,并且我们无法对本机SQL可靠地执行此操作.

JPQL抽象SQL实现及其提供者细节,并使ORM​​框架负责生成正确的SQL.

  1. 因此,通过在JPQL表单中使用Pagination,Spring只需要生成正确的JPQL,并且它将在ORM级别上进行解释以纠正SQL.

  2. 使用SQL时这样做意味着Spring知道如何为大量RDBMS生成正确的SQL,复制ORM功能,这是太多的开销.


Ste*_*e L 6

还有就是使用可分页与春数据的容量规划环境地政司原生查询的方式,这是提到在这里

您可以在此存储库中找到示例。

/**
     * @see DATAJPA-564
     */
    @Query(
            value = "select * from (select rownum() as RN, u.* from SD_User u) where RN between ?#{ #pageable.offset -1} and ?#{#pageable.offset + #pageable.pageSize}",
            countQuery = "select count(u.id) from SD_User u", nativeQuery = true)
    Page<User> findUsersInNativeQueryWithPagination(Pageable pageable);
Run Code Online (Sandbox Code Playgroud)

如果from子句或本机查询中有子查询,并且您希望对其进行动态排序,则排序功能将无法正常工作。可以通过在where子句中移动子查询来完成。如果中包含对象,则
Spring数据将追加到请求的末尾。(使用Spring数据1.10.3) " order by "SortPageable

更好的方法是在可能的情况下在jpql中转换本机查询。