2017-09-20 55 views
1

我使用Spring Boot 1.5.7和Spring Data JPA和Spring Batch。我使用JpaPagingItemReader<T>來讀取實體,並使用JpaItemWriter<T>來寫入它們。我想要做的是從某個數據庫表中讀取數據,將它們轉換爲不同的格式並將它們寫回不同的表格(我讀取原始json字符串,將它們反序列化並將它們插入到它們的特定表格中)。Spring批量查詢狀態變化

我不打算刪除處理它們後讀取的數據,而只是想將它們標記爲已處理。現在的問題是,將JpaPagingItemReader手柄讀起來很好,如果我作出這樣的查詢到的東西:

@Bean 
    public ItemReader<RdJsonStore> reader(){ 
     JpaPagingItemReader<RdJsonStore> reader = new JpaPagingItemReader<>(); 
     reader.setEntityManagerFactory(entityManagerFactory); 
     reader.setQueryString("select e from RdJsonStore e "+ 
           "where e.jsonStoreProcessedPointer is null"); 
     reader.setPageSize(rawDataProperties.getBatchProcessingSize()); 
     return reader; 
    } 

所以,如果沒有指針,它會只讀。我會在處理一個條目之後插入一個指針(批量處理,如我處理1000條目並將其所有ID發佈到指針表)。

如果我更改爲像這樣運行時返回的數據(它嘗試查詢的條目每批減少),ItemWriter(和JPA one)是否可以處理讀取的數據?

如果指針解決方案不適用,我應該如何設計DB-to-DB批處理作業?

我的源表看起來像這樣:

enter image description here

+0

不,它不能,基礎數據發生變化,並且對於每個頁面查詢重新執行,您將開始丟失數據。 –

+0

@ M.Deinum這是我想到的:( – appl3r

回答

0

如果你看看JpaPagingItemReader的代碼,方法doReadPage(),你會發現這條線,

Query query = createQuery().setFirstResult(getPage() * getPageSize()).setMaxResults(getPageSize());

其中createQuery()是,

private Query createQuery() { 
     if (queryProvider == null) { 
      return entityManager.createQuery(queryString); 
     } 
     else { 
      return queryProvider.createQuery(); 
     } 
    } 

因此,您會發現每個頁面都會重新創建/執行查詢,但頁碼不會根據新數據集重新計算,並且頁碼重新計算也沒有意義。

getPageSize()總是返回值在配置和getPage()回報設定最後計算的頁面數(前面處理的頁面+ 1),所以如果數據正在萎縮,你的程序將正常工作,如果頁面數計算也做了重新即你總是頁開始= 0,並且JpaPagingItemReader不會發生這種情況,所以您將會丟失M Deinum在註釋中指定的數據。

另外,按我的理解,新數據的添加將工作OK(提供了新的記錄被添加在末尾按排序即使作業運行過程中的數據的鎖定通常假定鍵)。

我認爲,目前的工作運行過程中標記一行作爲PROCESSED沒有任何意義,因爲已經由框架照顧(作爲一個記錄是沒有得到處理兩次)。

什麼,你可能需要的是標誌着一個紀錄下一個作業中處理運行並且可以通過更新一個獨立的標誌,它是不是WHERE條款部分(作業運行期間)以結束處理,然後工作 - 更新WHERE子句(您在WHERE子句中用於指示有關處理的記錄)的一部分的標誌。

+0

我想標記它們,因爲我的工作將由用戶手動啓動。如果他們再次啓動Job以獲得相同的資源,他們可能會複製數據,但我決定在我寫作時處理這個問題,而不是當我讀時。 – appl3r