2012-06-07 67 views
2

我正在使用Spring,Hibernate和JPA實體管理器。當同時獲取UI的不同區域(通過jquery/ajax)時,我想同步對JPA實體管理器的訪問,否則會導致對共享異常的共享引用。我如何實現這一目標?我有一個控制器調用後端的服務方法,負責調用entitymanager上的get/save等。同步訪問JPA EntityManager

+2

JPA實體管理器不是線程安全的,不應該被多個線程使用。每個線程應該有自己的實例。 –

+0

謝謝!如何爲每個請求注入一個單獨的實例(可能是ui控制器方法)?目前我正在將一個實體管理器(擴展持久模式)注入服務層。 – Supra

+0

鎖定對象可能有助於適當的模式 –

回答

1

您可以對特定模式的對象應用鎖定。

  • 實體管理器:entityManager.lock(entity, LockModeType.OPTIMISTIC);
  • 查詢:query.setLockMode(LockModeType.OPTIMISTIC);
  • NamedQuery:lockMode元素

鎖定模式OPTIMISTIC是同義READ & OPTIMISTIC_FORCE_INCREMENTWRITE


編輯:從文檔

如果事務T1呼籲類型LockModeType.OPTIMISTIC對 鎖的版本對象,實體管理器必須保證既不的 以下現象可以發生:

  • P1(髒讀):事務T1修改一行。另一個事務T2然後讀取該行並獲得修改後的值,然後T1已提交或回滾了 。事務T2最終成功提交 ;無論T1是提交還是回滾,以及在T2提交之前還是之後都是如此。

  • P2(不可重複讀取):事務T1讀取一行。另一個事務T2則在T1提交 之前修改或刪除該行。這兩個事務最終成功提交。

鎖定模式必須始終防止現象P1和P2。

+0

因此,如果我理解正確,那麼你所建議的是,我通過注入到spring控制器(目前它的服務)中引入entitymanager,然後使用我認爲需要的操作所描述的鎖定。我無法總是鎖定entitymanager,因爲並非所有操作都需要將其鎖定。 – Supra

+0

@Sup您不必鎖定entityManager,但只需要同時執行操作的所需對象。另外,我認爲沒有必要改變控制器/服務中的任何東西。這裏access或entityManager本身不同步,但是共享結果,它們的訪問是同步的。 –

+0

讓我再次解釋我的情況。我有一個調用serviceA的控制器方法a()。loadAllEntityA()和另一個也調用serviceA.loadAllEntityA()的b(),同時調用a()和b()。現在來自控制器方法,我想要一種方法來鎖定方法a()和b()的對EntityA的訪問。 – Supra