2013-03-01 200 views
1

假設我們有一個使用Hibernate的Web應用程序。 我的問題是關於發生什麼,如果來自不同用戶的兩個不同轉換訪問和操作同一個實體?例如,我們有一個名爲「學生」的實體,它有一個「年齡」字段。共享會話實體

Student student = session.load(1); // 1 is the id of some student 

,然後一個用戶操縱年齡字段e.g::現在,來自不同用戶的兩個不同的交易,使用Hibernate會話e.g獲取該實體 student.setAge(12); 第二位用戶是否看到完全另一個事務中的更改? 我的意思是如果第二個用戶在他自己的交易中調用 student.getAge(), 他是否看到新的值 - 12? 請注意,更改age屬性的第一個用戶尚未提交交易。

+0

提供完整的程序來獲得清晰的概念。通常在Web應用程序中,兩個不同的事務將使用「學生」實體的兩個不同對象。 – 2013-03-01 20:44:33

回答

1

這只是部分的冬眠問題。其他用戶是否看到未提交的數據取決於您是否已將數據庫連接的隔離級別更改爲讀取未提交。有沒有太多有用的理由你會這樣做,休眠會默認它讀取提交,除非被覆蓋。所以通常情況下,其他用戶在事務提交之前不會看到更改。

如果您已經降低了隔離級別,那麼最終歸結爲SQL實際發送到數據庫的時間。這是基於休眠的flush設置,可能在多層系統中難以預測。但基本上調用setAge不會將SQL發送到其他人可以看到的數據庫。導致刷新的東西必須發生,那些東西是依賴於配置的。

此外請注意,如果第二個會話在提交更新之前加載實體,即使第一個會話提交更新,第二個會話也不會自動奇蹟般地更新其內存實體,除非您明確地調用它的刷新。例如,

Time 1: Session A loads Student 1 
Time 2: Session B loads Student 1 
Time 3: Session A sets new age and commits 
Time 4: Session B gets Age, will still see old value 
Time 5: Session B calls refresh on Student 1 
Time 6: Session B gets Age, will see new value set in Session A 
+0

謝謝感謝您的詳細解答。這是我想讀的。 – friko 2013-03-01 20:53:01

+0

我明白了,再次感謝。 – friko 2013-03-01 21:02:05

0

請看這裏:Hibernate session thread safety。我認爲這與你所要求的非常相似。基本上,在多個線程中使用會話並不是一個好主意。因此,假設您正在使用不同的會話,第二個用戶將看不到更改。

+0

感謝您的快速回復。 – friko 2013-03-01 21:16:24

0

Hibernate擅長在多線程中併發更新,就像這種情況一樣。

首先,在這種情況下不存在線程安全問題。由於每個事務都擁有自己的會話,因此每個會話都將其加載的對象分別保存在其所謂的第一級緩存中。在兩個線程中的兩個實例將不會看到對方,其次,當多個事務更新同一記錄時,optimastic鎖定機制將工作。它是先到先得的模式。第一個提交的事務將會停止,第二個提交的事務將失敗並拋出異常。因爲hibernate會在其更新操作提交之前檢查versin屬性以查看版本是否爲原始版本。

看到http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html