2013-03-05 65 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