2011-02-08 59 views
2

我有一段代码使用休眠行为意外;在尝试了许多不同的调试策略之后,我想知道我对Hibernate会话/映射对象更新的理解是否不正确。这里是简化的场景:我有一个映射对象(MO),它是用id(long)和日期(日期/时间)定义的。 有一个主程序每60秒运行一次,根据日期/时间检查需要处理的任何MO。主例程运行在单个线程中。这里是伪代码:访问以前版本的数据对象的Hibernate查询?

main() 
// open session 
// get current date/time 
// query all mapped objects where date/time field < current date/time 
// for each mapped object which matches { 
// updateObject (session, current date/time, mapped object) 
// } 
// flush session 
// close session 

updateObject(Session s, Date currentTime, MappedObject mo) 
// changes to mo object 
// add 1 day to currentTime and update date/time field in mo 
// transaction begin 
// update mo object 
// transaction committed 

未显示:会话初始化工厂,异常处理例程

会话工厂配置了20(C3P0)的最大连接池大小。 默认设置正用于任何缓存。

问题

该查询返回的MO其日期值在未来(即日期/时间字段>当前日期/时间)。根据对象监视,MO中的日期/时间字段的值是旧的先前值(不是重新计算的更新值),这会强制查询将其提取并执行updateObject例程。

我假设更新通过直接监视数据库验证更新成功;此外,根据日志,没有任何事务异常被触发。

此问题间歇性地发生 - 有时,它每天发生几次,其他时间根本不发生。

平台细节

Hibernate的版本:3.3.2.GA

C3P0版本:0.9.1

JRE版本:1.6.0_16

我的想法

我的第一个想法是编码错误,但它确实似乎不是基地。我在想,如果以某种方式将对象的旧版本缓存在连接池中的某个Session对象中,并且出于某种原因,它会不时被拾取。

如果更新出现问题,我担心更大的影响。

我现在使用的是旧版本的Hibernate--迁移到一个新版本可能会有挑战性,但我想看看在走这条路线之前我是否误解了某些东西。

任何建议或指示结果将不胜感激 - 先谢谢了!

更新

移动到Apache DBCP似乎已经解决了这个问题。如果再次观察到问题,将会更新。

+0

无论您是否使用连接池,无论何时关闭会话(看起来您在做什么),会话缓存都将被清除。这似乎更有可能与二级缓存或查询缓存相关。这两个默认情况下都没有启用,您是否配置了应用程序以使用二级缓存或查询缓存? – Pace 2011-02-09 04:28:14

+0

@空间我看了二级缓存的文档(http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-cache) - 这不是什么我启用了。同上查询缓存选项(hibernate.cache.use_query_cache)。这很奇怪,因为我怀疑缓存,但根据所有迹象,它应该关闭。鉴于间歇性,我想知道它是否可能是旧版本中的错误。 – slau 2011-02-09 17:09:12

回答

0

有两两件事你可以试试...

1)设置以下休眠特性把语句缓存关闭: -

<property name="hibernate.c3p0.max_statements">0</property> 

如果还是不行...

2)不要使用C3P0,请尝试Apache DBCP以查看是否有相同的问题。它应该很容易换出。