有没有办法用JPA / hibernate滚动结果?

时间:2010-11-12 22:31:50

标签: java hibernate orm jpa toplink

我在Toplink中找到了一些提示

Query query = em.createQuery("SELECT e FROM Employee e ORDER BY e.lastName ASC, e.firstName ASC");
query.setHint("eclipselink.cursor.scrollable", true);
ScrollableCursor scrollableCursor = (ScrollableCursor)query.getSingleResult();
List<Employee> emps = scrollableCursor.next(10);

是否有jpa / hibernate备选方案?

5 个答案:

答案 0 :(得分:12)

据我所知,JPA没有任何标准。

使用Hibernate,我所知道的最接近的选择是Query / ScrollableResults API。来自文档:

  

10.4.1.6. Scrollable iteration

     

如果您的JDBC驱动程序支持   可滚动的ResultSet,查询   接口可用于获取   允许的ScrollableResults对象   灵活的查询导航   结果

Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " +
                            "order by cat.name");
ScrollableResults cats = q.scroll();
if ( cats.first() ) {

    // find the first name on each page of an alphabetical list of cats by name
    firstNamesOfPages = new ArrayList();
    do {
        String name = cats.getString(0);
        firstNamesOfPages.add(name);
    }
    while ( cats.scroll(PAGE_SIZE) );

    // Now get the first page of cats
    pageOfCats = new ArrayList();    
    cats.beforeFirst();    
    int i=0;    
    while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1) );

}

cats.close()
     

请注意,打开数据库连接   和光标是必需的   功能。使用   setMaxResult() / setFirstResult()如果你   需要离线分页功能。

答案 1 :(得分:5)

从其他答案来看,JPA不支持直接滚动,但是如果你使用Hibernate作为JPA实现你可以做到

javax.persistence.Query query = entityManager.createQuery("select foo from bar");
org.hibernate.Query hquery = query.unwrap(org.hibernate.Query);
ScrollableResults results = hquery.scroll(ScrollMode.FORWARD_ONLY);

它访问底层的Hibernate api以进行滚动,但您可以使用JPA查询的所有功能。 (至少对于标准查询,JPA api具有一些旧Hibernate api中没有的功能。)

答案 2 :(得分:3)

在基于List<E>个实例的大型项目代码中处理大量实体时, 我必须编写一个非常有限的List实现,只有Iterator支持来浏览ScrollableResults而无需使用List<E>重构所有服务实现和方法原型。

我的IterableListScrollableResults.java Gist

中提供了此实施方案

它还定期从会话中刷新Hibernate实体。这是一种使用它的方法,例如将所有非归档实体从DB导出为带有for循环的文本文件时:

Criteria criteria = getCurrentSession().createCriteria(LargeVolumeEntity.class);
criteria.add(Restrictions.eq("archived", Boolean.FALSE));
criteria.setReadOnly(true);
criteria.setCacheable(false);
List<E> result = new IterableListScrollableResults<E>(getCurrentSession(),
        criteria.scroll(ScrollMode.FORWARD_ONLY));
for(E entity : result) {
    dumpEntity(file, entity);
}

希望它有所帮助

答案 3 :(得分:1)

使用Spring Data也是一种选择。在那里,您可以指定查询并作为参数传递“PageRequest”,您可以在其中指明页面大小和页码:

Page<User> users = repository.findAll(new PageRequest(1, 20));

为此,您需要扩展PagingAndSortingRepository。

就像对结果进行分页的另一种选择。

当然,在下面,它使用的是Hibernate,Toplink或你配置的任何JPA实现。

答案 4 :(得分:0)

在JPA中,您可以使用query.setFirstResult和query.setMaxResults