2013-03-05 62 views
7

我有一张我想通过Spring Data Repository访问的大表。如何使用Spring Data Repositories处理大量数据?

目前,我试图延长PagingAndSortingRepository界面,但似乎我只能定义返回列表的方法,例如:

public interface MyRepository extends 
     PagingAndSortingRepository<MyEntity, Integer> 
{ 
    @Query(value="SELECT * ...") 
    List<MyEntity> myQuery(Pageable p); 
} 

在另一方面,随PagingAndSortingRepository回报findAll()方法一个Iterable(我想这些数据没有加载到内存中)。

是否可以定义也返回Iterable和/或不一次加载所有数据到内存的自定义查询?

有处理大型表格的方法吗?

+0

'List'实现'Iterable'接口,所以你的自定义查询方法确实返回'Iterable'。 – zagyi 2013-03-05 19:13:43

+0

我想当我使用findAll()时,Spring Data不会加载内存中的所有内容,我错了吗?我将编辑该问题。 – 2013-03-05 20:20:25

+0

[底层实现](https://github.com/SpringSource/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java#L247 )只是检索一个列表,所以它不是那么复杂。 – zagyi 2013-03-05 20:33:47

回答

9

我们在这里有经典的咨询答案:这取决于。由于该方法的实现是专门针对商店的,因此我们依赖于底层商店API。在JPA的情况下,没有机会提供流式访问,因为….getResultList()返回List。因此,我们还将List公开给客户端,因为特别是JPA开发人员可能会习惯使用列表。所以对于JPA唯一的选择是使用分页API。

对于像Neo4j这样的商店,我们支持流式访问,因为存储库在CRUD方法以及查找器方法的执行上返回Iterable

+0

嗨,奥利弗,谢谢你的解释。我创建了一个Iterable来抽象分页的东西。如果你有一段时间,我会非常感谢任何关于代码/方法的反馈。再次感谢你:) https://gist.github.com/josericardo/5102304 – 2013-03-06 19:36:58

+1

我通常会建议不要做这样的事情。处理一个默默提取数据的包装很容易,但是你会遇到各种各样的问题,因为你没有真正控制会话边界,所以你会遇到'LazyLoadingException'。访问一个'Page',迭代内容并重复如果Page.hasNext()'为'true',会出现什么问题?这至少可以让你明白,除非你处于更广泛的范围事务中,否则你会在存储库级别获得会话边界。 – 2013-03-07 09:16:09

+0

感谢您的反馈和时间:) – 2013-03-07 17:47:35

2

implementationfindAll()只是将所有实体的整个列表加载到内存中。它的Iterable返回类型并不意味着它实现某种数据库级别的游标处理。

另一方面,您的自定义myQuery(Pageable)方法将只加载一页实体,因为生成的实现将遵循其参数Pageable。您可以将其返回类型声明为PageList。在后一种情况下,您仍然会收到相同(受限制)数量的实体,但不会收到Page另外携带的元数据。

所以,你基本上做了正确的事情,以避免在自定义查询中加载所有实体到内存中。请致电related documentation here

+0

第二个链接已损坏。现在它是https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.special-parameters – kolobok 2018-02-28 10:54:50