2011-04-06 66 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();