2011-12-21 33 views
3

我想遍歷數據庫中的記錄並進行更新。但是,由於更新過程需要一些時間並且容易出錯,所以我需要a)在每次更新之後,不要讓db等待(例如使用)和b)提交。 第二件事是這是在多個線程中完成的,所以我需要確保如果線程A正在處理記錄,線程B正在獲得另一個記錄。 我怎樣才能用hibernate實現這個合理的?如何在休眠狀態下正確地迭代db記錄

爲了給出一個更好的主意,下面的代碼會被多個線程,所有線程共享RecordIterator的單個實例執行:

Iterator<Record> iter = db.getRecordIterator(); 
while(iter.hasNext()){ 
    Record rec = iter.next(); 
    // do something lengthy here 
    db.save(rec); 
} 

所以我的問題是如何實現RecordIterator。如果在每個next()我執行查詢,如何確保我不返回相同的記錄兩次?如果我沒有,哪個查詢用來返回分離的對象?在一般方法中是否存在缺陷(例如,使用每個線程一個RecordIterator並讓db以某種方式處理同步)?附加信息:有很多記錄可以在本地保存(例如,在一組處理過的記錄中)。

更新:由於整個過程需要一些時間,可能會發生記錄狀態更改。由於查詢結果的排序可能會發生變化。我想解決這個問題,我不得不在數據庫中標記記錄,一旦我將它們返回給他們進行處理...

回答

2

嗯,如何將某些有界阻塞隊列中的讀者線程中的對象推送出去,讓更新器線程讀取從那個隊列中。

在您的閱讀器中,使用setFirstResult/setMaxResults進行一些分頁。例如。如果您的隊列中最多有1000個元素,則一次填充500個元素。當隊列已滿時,下一次推送將自動等待,直到更新者獲取下一個元素。

+1

嗨,謝謝你的回答。我很抱歉,但我沒有想到我在問題更新中描述的另一個問題。我想解決這個問題,我不得不在數據庫中標記記錄,一旦我將它們返回進行處理... – roesslerj 2011-12-21 13:34:01

+0

我在過去做了類似的事情。我最終做的是創建一個標記表,用於存儲已更新的條目。我正在使用SpringBatch BTW來處理排隊和分頁。 – greyfairer 2011-12-21 15:15:56

0

我的建議是,由於您共享主迭代器的實例,是運行所有使用共享Hibernate事務的線程,與在開始一個負載並在最後一個很大的節省。您所有的數據加載到一個單一的「設置」,你可以使用你的線程(注意鎖定的,所以你可能要拆斷爲每個線程一節,或以某種方式讓你不管理共享資源遍歷t重疊)。

Hibernate解決方案的優點在於記錄不會立即保存到數據庫,因爲您正在使用事務,並且存儲在hibernate的緩存中。最後,他們都會立即寫回數據庫。這樣可以節省那些你擔心的昂貴的數據庫寫操作,再加上它爲每次迭代提供了一個實際的對象,而不僅僅是一個數據庫行。

我看到你更新在處理過程中記錄的狀態可能會發生變化,這可能總是會導致一個問題。如果這是一個持續運行的過程或長時間運行,那麼我使用hibernate解決方案的建議是使用較小的集合,是的,添加一個標記來標記已更新的記錄,以便當您移動到下一集時可以拿起那些沒有被觸摸過的東西。

+0

這是我最初的想法。但是,它有一些嚴重的缺陷: a)如果我遇到任何錯誤(這可能是我的情況),所有中間結果都會丟失。 b)所有的數據驗證都是在最後完成的,所以如果我產生了任何不一致的情況,我只會在所有結果被計算並丟失後纔會注意到(見a))。 c)我會遇到內存問題,因爲我需要保留內存中的所有記錄,直到最終提交。 – roesslerj 2011-12-22 13:06:57

相關問題