我正在开发一个项目,该项目在过去几个月中开发了一个涉及对象更新的令人难以置信的恼人错误。在休眠状态下更新时,某些对象(最明显的用户)永远不会被标记为脏和刷新。例如:
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之外,拦截器上的所有适当方法都被hibernate调用。我最初的假设是,这是分离对象的问题,因为我们将用户对象存储在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 :(得分:0)
尝试禁用hibernate二级缓存。实际上,你可以发布你的cfg.xml吗?
答案 1 :(得分:0)
Finbarr部分正确它几乎肯定是一个缓存问题,但不是二级缓存。通过forcing Hibernate进行更新,无论是否更改,现在都可以正常保存。
session.evict(object);
session.update(object);
答案 2 :(得分:0)
在我的项目环境中,我偶然发现了一段代码,它完全符合您上面提到的内容:逐出然后更新。 您调查中的其他内容是否对此问题提出了更多见解。错误或没有错误 你有没有报告这种行为/ bug来休眠和/或你是否有参考JIRA? 你的hibernate版本是什么?
关于潜在原因: -1-您在查询级别或对象级别提到了只读会话但不是只读 你检查过对象是否没有被逐出会话(EvictEventListener) -3-您是否检查过该对象没有再次更改为其原始状态,因此不需要使用该对象的较旧(分离)版本再次更新或再次更新调用
任何意见, 问候, 克里斯托夫
答案 3 :(得分: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();