HIbernate对象处理

SSH的j2ee开发中,需要遇到一个hibernate直接操作数据库,不通过对象,直接对数据库进行操作。
Spring的orm包中,对hibernate的数据库操作进行了封装,封装以后,可以直接调用HibernateTemplate类的实例,进行DB操作。因为,需要实现对数据库操作,查了一下资料可以直接调用HibernateTemplate的bulkUpdate()操作来执行数据库的操作。
问题主要出现在这里了,这是我写的一段的HQL语言,使用bulkUpdate接口来执行的。
			HibernateTemplate ht = getHibernateTemplate();
			int num = ht.bulkUpdate("UPDATE Option op set op.optionMean= ?  where op.optionMean= ?", new Object[]{newDimname,oldDimname});

理应我的这段代码会update DB中的Option表的相关数据。在tomcat下,这段code成功的跑完了,也没有抛出任何异常信息,但是就是DB中的相关表中没有更新。
然后我再测试组件里面同样的执行了这段code,没有任何问题。
自己查资料分析,也没有得出一个很清晰的解决思路。在水木上问了,基本认为:1.是transaction基本上是有问题的;2.或者Spring对hibernate的transaction托管会出现问题。我们来依次分析这些原因:
1. 查看原始的HibernateTemplate.bulkUPdate的源代码
	public int bulkUpdate(final String queryString, final Object... values) throws DataAccessException {
		return executeWithNativeSession(new HibernateCallback<Integer>() {
			public Integer doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createQuery(queryString);
				prepareQuery(queryObject);
				if (values != null) {
					for (int i = 0; i < values.length; i++) {
						queryObject.setParameter(i, values[i]);
					}
				}
				return queryObject.executeUpdate();
			}
		});
	}

从源代码中我们可以看到基本上Spring orm包中做的封装工作主要是两部分:
a.session管理。
b.简化hql语言的使用。
然后我们在查看相应的log信息:
INFO  com.sgcp.system.entity.OptionDAO  - 更新的数据库条目数量:80 com.sgcp.system.entity.OptionDAO.replaceDimName(OptionDAO.java:43)
说明这个transaction已经执行了,并且返回了相应更新的数据库的行数。
2.SpringFrame 的session管理,相应执行transaction应该都是没有问题的,因为在测试的code中也是由SpringFrame来管理的,执行是成功的。所以SpringFrame对hibernate的托管是没有问题的。
所以现在已经判定query已经被执行了,那么现在是什么问题呢?
在查看资料中,发现hibernate中的执行会有一个cache,为了减少code对db的hits。因为cache有一个write-behind策略,就是update的对象,对那些update的对象,如果在最近没有再read的话,那就晚些写回DB中,这样如果要再次update的话,就可以少一次update。
但是因为,我在执行完query,有对session进行了flush过,所以这种可能也被排除了。
为了确定我的判断,我后来用直接从db中用对象方式读取符合条件的Options,set相应的属性值,后在attachDirty这些对象,但是也没有用。
最后再仔细排查code以后,原来这些rows对应的对象其实已经被读取进来了。就是说那些对象已经被存储到了hibernate中的cache中了。
这个就是问题的关键所在了,如果我们直接update数据库了的话,database中的那些rows和在hibernate中的数据缓存中的相应的对象就会变成脏的对象。
所以我猜测就是有可能是hibernate在检查bulkUpdate的操作时,会检查原先的缓存中,是否已经有要更新的行对应的对象,有的话,就不允许进行这类的操作。
后来,我直接取出hibernate中缓存中的相应对象,然后更新后,对这些对象进行attachDirty().数据库就成功更新的了。
但是就是不知道为什么hibernate没有报错。

你可能感兴趣的:(Hibernate,J2EE)