2016-09-29 55 views
0

我有有以下類似的關係實體Hibernate項目:開球事件發生後中的多個對象的Hibernate事務更新

Car { 
    String name; 
    Engine engine; 
} 

Engine { 
    String name; 
} 

我們有一個外部系統(Web服務,一個黑盒子),這需要與上述實體所做的更改進行更新,但是,外部系統不會使CarEngine之間的區別:

RemoteCar { 
    String name; 
    String engineName; 
} 

同步過程涉及獲得的實例,更新從CarEngine更改的值,然後發送更新請求。

我試圖用一個PostUpdateEventListenerrequiresPostCommitHanding返回true揭開序幕的應用程序事件更新外部系統,但如果Car的名字和Engine的名字都在同一事務的更新,我收到兩個事件,開始與外部系統的兩個同步。

有沒有辦法確保我只接收我需要的事件?可悲的是Engine的一些更新是直接執行的(EngineDao.get(1).setName()),這意味着Car從未涉及 - 我可以輕鬆地工作我的方式備份樹以獲得我的Car實例,但我不知道如何判斷是否更新到EngineCar的更大更新或Engine的自包含更新的一部分。

回答

1

我建議不要在每個偵聽器回調中與遠程系統同步,因爲如上所述,它會成爲潛在的I/O瓶頸。相反,我會建議維護一個特定於事務的緩存並複製一次。

PostUpdateEventListener火災,這樣做如下:

  1. 檢查當前的事務有一個緩存。如果沒有,請創建緩存並在提交事務回調之前註冊一個(稍後)。
  2. 對於每個更新事件,請檢查緩存以查看是否已獲取相應的RemoteCar。如果有,請相應地更新緩存。如果它不在緩存中,則從遠程系統獲取並更新緩存實例。

在事務的提交階段,會觸發before commit事務回調,它會迭代緩存實例並根據您的API,向您的遠程系統發送批量更新(1個I/O調用)更新所有修改的RemoteCar實例。

這將允許您的用例,其中2個更新觸發2個同步點,以減少到單個遠程獲取,2個本地更新和1個複製更新回到外部系統。

+0

謝謝你。你將如何管理你的緩存?我可以使用具有PostUpdateEvent.getSession()。getTransaction()作爲IdentityHashMap中的鍵值的Map嗎? (當然,正確同步) – Rich

+0

是的,這正是我在管理與Envers中的休眠會話有關的審計進程緩存時所做的。 – Naros