Saturday, April 11, 2009

Myeclipse Hibernate Session 在查询数据库后不更新的问题解决方案

最近的一个项目, 在更改数据库之后,再次查询,发现返回值总是在变化,有时候和数据库一致,有时候却仿佛回滚到了原来的状态。 这个问题是查询的时候,使用了以前的Session缓存。 虽然在数据更改之后,Hibernate会更新缓存,但是以前的session没有在finally关掉,所以缓存存在周期超过了一个transaction; 同时,又没有设置查询不使用缓存,所以造成了这个问题。

这个问题应该非常的常见,因为使用的代码是Hibernate生成的。 修复的办法是修改Hibernate生成的代码,设置Session不使用缓存(session.setCacheable ),然后在finally里面关掉Session.close(),并且每次都把Session清空(这个是在HibernateSessionFactory里面的getSession里面,加上Session.clear())。三管齐下,不过这是专门用来解决需要每次查询都更新的情况。 具体的对缓存的管理,大家还是按照项目的需求具体设置吧。

首先,遗弃原始的getSession() 方法, 使用新版的getClearSession() 方法。

    public static Session getClearSession() throws HibernateException {
Session session = (Session) threadLocal.get();

if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
session.clear();
return session;
}
然后在需要的地方调用新方法,并设置关闭缓存

    public List findRefreshAll() {
log.debug("finding all TkTimeEntry instances");
try {
String queryString = "from TkTimeEntry";
Query queryObject = getClearSession().createQuery(queryString);
queryObject.setCacheable(false);
return queryObject.list();
}
catch (RuntimeException re) {
log.error("find all failed", re);
throw re;
}
}
最后,在transaction使用session的时候,关闭session.
    public List<TkTimeEntry> RetrieveAllTimeEntry() {
TkTimeEntryDAO dao = new TkTimeEntryDAO();
Transaction trans = null;
try {
trans = dao.getSession().beginTransaction();
List<TkTimeEntry> timeEntryList = dao.findRefreshAll();
trans.commit();
return timeEntryList;

}
catch (HibernateException e) {
if (trans != null)
trans.rollback();
log.fatal(e);
return null;
}
finally
{
dao.getSession().close();
}

}

1 comment:

IT said...

Hibernate Online Training Hibernate Online Training Hibernate Training in Chennai Hibernate Training in Chennai Java Online Training Java Online Training Hibernate Training Institutes in ChennaiHibernate Training Institutes in Chennai