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

时间:2015-02-15 18:32:22

标签: java spring spring-data-jpa

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

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

但是,使用本机查询无法实现相同的功能,因此

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

不起作用。

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

3 个答案:

答案 0 :(得分:31)

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

给定一个存储库:

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

您可以向实体添加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 {
}

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

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

这实际上很不错。

答案 1 :(得分:11)

这是春季数据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功能,这是一个过多的开销。

答案 2 :(得分:6)

有一种方法可以将Pageable与具有Spring数据的SpEL容量的本机查询一起使用,提到here

您可以在this repository中找到一个示例。

/**
     * @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);

如果from子句或您的本机查询中存在子查询并且您希望对其应用动态排序,则sort functionnality将无法正常工作。可以这样做的方法是在where子句中移动子查询 如果" order by "中有Sort个对象,则Spring数据会附加到您的请求Pageable结束。 (使用Spring数据1.10.3)

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