2014-09-28 103 views
0

我繼承了一個我以前從未使用過的使用Hibernate的應用程序。這個應用程序中的'標準'編碼實踐(這些人在很多方面都是可怕的程序員)是爲每個查詢/更新創建一個會話,執行查詢/更新,然後flush()和close()會話。到現在爲止,我沒有這個問題,但現在我是。情況是這樣的:爲什麼查詢後的flush()會導致數據庫更新?

  1. 查詢數據庫的UserObject因爲他們登錄
  2. 保存UserObject到網絡存儲,爲用戶的web應用會話
  3. 在UserObject使用價值修改屏幕的外觀/行爲

2是新件 - 以前的代碼已經保存了一些單獨的UserObject屬性值,或者在用戶每次點擊某件事後的每次操作中每次查詢數據庫。但是現在我在內存中存儲/保存UserObject,對這個表/對象的其他查詢會導致數據庫掛起Hibernate在查詢後的flush()期間執行的更新失敗。爲什麼Hibernate只是在查詢對象時執行數據庫更新?我知道我是一個老學校的程序員,其中數據庫事務很小(開放,讀/寫,提交/關閉),並且從來沒有在內部進行用戶交互,因爲這會使行,表和表空間鎖升級。所以也許我不瞭解Hibernate持久性如何工作以及如何編碼。在查詢之後,flush()永遠不會被使用嗎?每個用戶的webapp登錄會話應該只有一個「會話」對象? Hibernate持久性是否應該消除必須實際編碼'更新',因爲它會在封面下自動發生?這意味着編碼模型是查詢hibernate/db/Java對象,讓用戶修改字段,讓代碼更新Java對象,然後使用一個flush()+ commit()方法調用更新數據庫中的所有內容?

**更新**

下面是我繼承的代碼示例。每個DB對象的整個代碼中都有100多種類似的方法。

public static List<BeanObject> GetObjectList() { 
    List<BeanObjec> list = null; 
    Session session = factory.openSession(); 
    try { 
     list = (List<BeanObject>) session.createQuery("from BeanObject").list(); 
    } catch (Exception e) { 
     // System.out.println("========="+e.getMessage()); 
    } finally { 
     session.flush(); 
     session.close(); 
    } 
    return clist; 
} 

這一直工作得很好,直到最近幾個月,當我試圖「保持」到這些返回的對象之一。一旦這個單個對象被保存在web-session-memeory中,另一個調用這個方法的.list()調用創建了3個對象,這很好,但是flush()調用爲所有3個對象創建了SQL UPDATES!爲什麼要更新未修改的對象?

+2

難道你不覺得Hibernate文檔可以回答這些問題?數據庫事務處理應該儘可能短(但不要太短,否則會影響數據的一致性)。沖洗是自動的。保存修改的狀態是自動的。每筆交易都應有自己的會話。 – 2014-09-28 16:33:00

+0

通過「每一筆交易都應該有自己的會話」你的意思是每個web交易或每次用戶點擊時調用一個DB行動,對不對?你並不是說每個SQL語句都應該有自己的事務。 – user3708842 2014-09-29 18:59:30

+0

我的意思是每個交易,在數據庫中,ACID,它的含義。聲明是交易的一部分。一個HTTP請求可以執行0,1個或更多事務。通常1. – 2014-09-29 19:18:01

回答

1
  1. 默認情況下,flushcommit之前是多餘的,因爲它無論如何都會發生;

  2. 默認情況下休眠並不是SELECT FOR UPDATE;

  3. 你是正確的,一個Hibernate Session應該跨越一個完整的請求處理。但是,從每個請求的單個事務的業務級語義來看,這應該是顯而易見的。其他任何事情都會非常不尋常,但所有事務仍然會在同一個會話中發生,最接近映射到一個租用的數據庫連接(儘管不是100%)。

+0

我在上面發佈了一些示例代碼,在整個應用程序中,每個SQL STATEMENT都有其自己的會話。我有一種感覺,這個代碼的編寫者不知道如何使用Hibernate ...但我還是想知道爲什麼Hibernate是一個沖洗期間執行UPDATE語句()查詢後立即在沒有對象被修改。 – user3708842 2014-09-29 19:27:51

0

要理解Hibernate持久性模型,您需要將您的思維從手動DML語句更改爲entity state transitions

休眠入隊的所有實體的狀態轉換,只propagate them during a Session flush。該自動沖洗將會刷新之前HQL/JPQL和標準執行查詢,但它might not trigger a flush for native SQL queries

默認沖洗前查詢是有用的,因爲SQL查詢應針對當前運行的事務期間發佈的最新變化中運行。在本機查詢之前,你可能只需要手動刷新,但對於實體查詢,如果你堅持使用默認的AUTO刷新模式,Hibernate應該照顧它。

+0

感謝您訪問該博客的鏈接 - 這非常有幫助。請看看我上面的更新。 – user3708842 2014-09-29 19:13:56

+0

該沖洗在該特定用例中是無用的。我無法想象爲什麼你會看到那些方法中的更新,因爲你打開一個新的會話並且不會改變任何東西,除非你使用屬性級訪問類型,並且getters返回的是不同於原始類型的集合。 – 2014-09-29 20:53:56

相關問題