2011-04-06 69 views
1

我正在研究一個項目,在過去的幾個月裏發展了一個涉及對象更新的令人難以置信的煩人的錯誤。在hibernate中更新某些對象(最顯着的是用戶)永遠不會被標記爲髒和刷新。例如:休眠不刷新修改對象到數據庫

Session session = factory.openSession(interceptor); 
Transaction tx = session.beginTransaction(); 

Object object = session.load(someId); 
// Modify object ... 
session.update(object); 

tx.commit(); 

session.flush(); 
session.close(); 

所有的攔截相應的方法得到的,除了Interceptor.onFlushDirty和Interceptor.findDirty休眠調用。我最初的假設是,這是一個分離對象的問題,因爲我們將用戶對象存儲在http會話中;然而,重構刪除所有分離的對象並沒有解決問題。

該交易肯定會落實,會話將在完成時被刷新並關閉。我也加倍檢查以確保會話不處於只讀模式。

我也嘗試使用Session.merge來代替Session.update,沒有任何效果。當使用Session.merge時,返回的對象包含正確的更新信息,但數據庫再次不會更新。

我找到了this這個問題似乎描述了一個類似的問題(相關因爲我工作的對象存儲自定義枚舉字段)和good description of Hibernate's dirty checking mechanism但除此之外,信息一直稀疏。

我cfg.xml文件看起來是這樣的:

<property name="hibernate.current_session_context_class">thread</property> 
<property name="hibernate.default_batch_fetch_size">1024</property> 
<property name="hibernate.order_inserts">true</property> 
<property name="hibernate.order_updates">true</property> 
<property name="hibernate.show_sql">false</property> 

<property name="hibernate.c3p0.aquire_increment">1</property> 
<property name="hibernate.c3p0.initial_pool_size">1</property> 
<property name="hibernate.c3p0.min_size">4</property> 
<property name="hibernate.c3p0.max_size">32</property> 
<property name="hibernate.c3p0.idle_test_period">100</property> <!-- seconds --> 
<property name="hibernate.c3p0.timeout">600</property> <!-- seconds --> 

<property name="hibernate.cache.use_second_level_cache">false</property> 
<property name="hibernate.cache.use_query_cache">true</property> 
<property name="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</property> 

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> 

<property name="hibernate.jdbc.fetch_size">1024</property> 

<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property> 

<property name="hibernate.search.worker.execution">async</property> 
<property name="hibernate.search.default.directory_provider">org.hibernate.search.store.RAMDirectoryProvider</property> 
<property name="hibernate.search.default.indexwriter.batch.ram_buffer_size">256</property> 
<property name="hibernate.search.default.optimizer.transaction_limit.max">1000</property> 

更新:我曾經嘗試都禁用和啓用Hibernate的二級緩存爲Finbarr建議沒有影響。

任何人都可以嘗試其他事情上的任何建議?

回答

0

Finbarr部分正確它幾乎肯定是一個緩存問題,但不是二級緩存。通過forcing Hibernate來做更新,而不管它是否改變了所有東西現在正在保存正常。

session.evict(object); 
session.update(object); 
0

嘗試禁用hibernate的二級緩存。其實,你可以發佈你的cfg.xml嗎?

+0

二級緩存是最近才啓用,在此之前,這是一個問題。 – 2011-04-07 17:35:00

0

在我的項目的情況下,我絆倒了一段代碼,你所提到的正是上面所做的:逐出然後更新。 您調查中的其他元素是否在這個問題上提供了更多見解。錯誤或沒有錯誤後遺症 您是否已將此行爲/錯誤報告爲休眠和/或您是否具有該JIRA的參考? 什麼是您的hibernate版本?

在潛在原因: -1-你提到只讀會話,但不是隻讀的查詢級別或對象級別 -2-你檢查的對象中未充分利用會議(EvictEventListener)逐出 -3-你檢查的對象沒有被再次改變到原來的狀態,於是又無需更新或其他更新的呼叫與對象的較早(分離)版本

任何輸入讚賞, 問候, Christophe

+1

如果我仍然爲公司工作並有權訪問代碼庫,我很樂意爲您提供這方面的意見。 – 2012-08-08 06:05:09

0

問題出在代碼中:你一個在刷新會話之前重新提交事務! 您必須刷新將「同步」會話狀態與當前的事務,然後提交事務會話:

Session session = factory.openSession(interceptor); 
Transaction tx = session.beginTransaction(); 

Object object = session.load(someId); 
// Modify object ... 
session.update(object); 
session.flush(); 

tx.commit(); 
session.close();