2013-03-03 130 views
0

我有一個問題會發生什麼,如果兩個不同的Web用戶在同一個實體上工作。 例如共享實體有四個字段:休眠共享實體競爭條件

class HibernateSharedEntity 
{ 
int id; 
int a; 
int b; 
int c; 
int d; 
} 

現在,兩個用戶都在同一時間打開一個事務。其中之一是更新這個實體,第二個用戶正在閱讀這個實體。下面的步驟將解釋它好得多:

時間1:休眠實體被存儲在數據庫中,並且具有值:A = B = C = d = 0,ID = 1。
時間2:用戶1打開新的事務。
時間3:用戶1讀取HibernateSharedEntity其中id = 1周
時間4:用戶1正在修改所有字段:例如a = 2,b = 3,c = 4,d = 5。
時間5:用戶1正在提交事務。
時間6:休眠正在更新a = 2
時間7:休眠正在更新b = 3
時間8:現在用戶2打開一個新事務並讀取該共享實體。問題: 他檢索了什麼?他是否接受了一個半更新的實體: a = 2,b = 3,c = 0,d = 0?
時間9:休眠正在更新C = 4
時間10:休眠正在更新d = 5

我想避免半更新實例。這是我的應用程序的關鍵點。 如果第二用戶希望檢索該共用實體,我想的是,第二 用戶只能處於兩種狀態,在A = B = C = d = 0的狀態(以前提交)或 a = 2的讀此共享實體,b = 3,c = 4,d = 5狀態(提交後)。我知道hibernate可以使一個插入來更新所有這些值,但在我的應用程序中它似乎更復雜,因爲這個共享實體與其他共享實體有關係,也可以由User1更新。所以從現在開始,hibernate不能讓一個插入來更新這兩個共享實體。因此,當User1在一個事務中更新更多的共享實體時,是否有這種可能性,User2可以以「非同步狀態」讀取這些實體。我的意思是當一個實體更新時,但另一個實體沒有更新?

我認爲它可以複雜,所以我會嘗試更多的解釋: 在我的應用程序共享實體進行同步。例如。有兩個共享實體,如:
entity1 = {a = 1,b = 2,c = 3,d = 4}
entity2 = {a = 5,b = 6,c = 7,d = 8}

現在用戶1想要更新這些實體,例如到這種狀態:
使用實體= {A = 0,B = 0,C = 0,d = 0}
ENTITY2 = {A = 0,B = 0,C = 0,d = 0}

。而用戶1正在更新事務,用戶2希望讀取這些共享實例和 我想避免,即用戶2被readeing在這樣的狀態下這些實體:
使用實體= {A = 0,B = 0,C = 0,d = 0}
ENTITY2 = {A = 5,b = 6,C = 7,d = 8}
正如你可以看到,使用實體被更新,但ENTITY2不是。這是我申請中的關鍵點,並不存在這樣的情況。我怎樣才能避免這種情況?冬眠是否照顧這個? 預先感謝您。

回答

1

您的第一個場景是不可能的。 Hibernate在事務提交之前將更改寫入數據庫,而不是之後。用戶2將讀取已提交給數據庫的內容,因爲它在第一個事務提交後讀取實體。如果用戶2在提交第一個事務之前從數據庫中讀取數據,它將讀取第一個事務開始之前的狀態(只要數據庫隔離級別是默認的READ_COMMITTED)即可。

Hibernate應用程序與其他數據庫應用程序沒有區別:事務的ACIDity由數據庫處理,而不是由Hibernate處理。實體,順便說一句,不共享。每個Hibernate會話都有自己的給定實體副本,其中包含從事務中的數據庫中讀取的數據。

閱讀有關數據庫事務和ACID的信息。不管你是否使用Hibernate都不會改變任何東西。

+0

Hibernate確實包含二級緩存,所以在提交實體時,這些存儲在二級緩存中,而不是數據庫中。我對嗎 ? – friko 2013-03-03 22:10:50

+0

編號實體始終保存在數據庫中。它們也可能存儲在二級緩存中,但緩存不會替換數據庫。而二級緩存默認是禁用的。您必須啓用它,並選擇使實體可緩存,才能將其存儲在二級緩存中。我的建議是:除非您已經測量過它是絕對必要的,否則不要混淆二級緩存。特別是如果你沒有完全理解Hibernate和事務如何在沒有這個緩存的情況下工作。 – 2013-03-03 22:13:26

0

事務是DB(和hibernate)中的原子操作。數據庫引擎保證用戶不會得到一半更新的實體(如果您配置事務管理權限;))。

如果您的應用程序依賴於數據完整性,則還應該實施某種實體鎖定。對於大多數用例而言,樂觀鎖定就足夠了。 (如果不熟悉,請嘗試使用Google搜索這一術語)。