2013-03-27 35 views
1

我對JPA比較陌生,對如何最好地樂觀鎖定和刷新實體感到非常困惑。我想在我的項目中使用一套通用的方法來處理這個問題。我應該如何最好地鎖定和刷新JPA實體?

我可能在不知道實體狀態的方法中調用鎖定/刷新方法,它可能已經傳遞了一個detatched或new/not saved實體對象以及先前從數據庫讀取的實體對象。爲了簡單起見,我希望我的效用方法能夠處理所有可能性。語義我想實現的方法是:

myEntity所refreshAndLock(myEntity所E)
再從數據庫讀取實體和樂觀鎖定它,或者什麼都不做的實體尚未保存到數據庫中。分離的實體也將被重新讀取並鎖定,並返回管理版本。

MyEntity refresh(MyEntity e)
只需重新讀取實體,或者對於尚未保存到數據庫的實體執行任何操作。分離的實體也將被重新閱讀。

myEntity所lockAndNotRefresh(myEntity所E)
鎖定在內存中的實體版本(可能已經過時)

任何提示或鏈接欣然接受。我還沒有設法找到明確的指導,我很驚訝,因爲這似乎是一個普遍的要求。

回答

1

1,我的主要建議是:不要試圖實現你自己的通用數據訪問層。你有EntityManager在你手中爲你做所有的東西。保持你的代碼簡單,不要過度使用。對於通用層,您很可能會引入新問題並降低可維護性。

第二,你必須問自己,爲了決定鎖定,你的應用程序的典型用例是什麼。鎖定總是會帶來瓶頸問題和可能的死鎖問題。因此,如果您的應用程序讀取的內容比寫入內容多得多,或者可能不會同時訪問同一個實體,那麼最好使用樂觀鎖定,然後處理異常。 JPA爲您提供版本控制,因此您始終知道其他某個線程是否改變了您的對象。如果您確實需要悲觀鎖定,那麼請繼續爲這些情況進行設置。

+0

感謝您的建議。我假設使用JPA版本控制進行樂觀鎖定。我不清楚什麼樣的EntityManager接口調用組合可以在未知狀態的實體上達到所需的結果。在我看來,在許多情況下,您需要知道實體被鎖定的狀態(新的,持續的,分離的),這會降低代碼的可重用性。我對上述方法的想法是集中與這些模式相關的代碼,而不是通過代碼庫重複它。但是,當然,如你所建議的那樣,有優點和缺點。 – Jonathan 2013-04-10 21:36:09

+0

基本上你只有兩種可能性:實體或者由EntityManager管理或者不管理。在第一種情況下,您對該實體所做的所有更改都將在事務結束時自動與底層數據庫同步。在第二種情況下,如果您從其他位置獲取該實體或通過新創建該實體,則可以使用merge()使其進行管理。那麼,你爲什麼覺得,你必須關心實體的狀態? EntityManager爲你做。在樂觀鎖定的情況下(是的,通過@Version),你必須關心可能的OptimisticLockExceptions。 – 2013-04-11 05:48:35

+0

關於你不得不重複代碼的擔心 - 正如我上面所說的,實際上沒有關心實體的代碼,你所要做的就是讓EntityManager知道它。那麼你當然可以將一些常見的用例分解爲在業務邏輯中不多次使用它們。你可能會關心一箇中心點的例外情況。但是,在大多數情況下,你不能也不應該把所有的實體都視爲同一個實體,它可能會因用例和用例的不同而異。 – 2013-04-11 05:52:21