SSH 框架中 service 里面有 sql 和 对象存储,执行顺序问题 Spring 事务提交顺序

来源:互联网 发布:叮咚智能音箱软件 编辑:程序博客网 时间:2024/06/07 19:08
在SSH 框架中,spring 2.5 + hibernate 3 + struts 2
由于公司项目比较老,jar包当然是不能修改的。但是最近遇到一个问题(公司里有其他同事也遇到过,只是我不知道,公司的分享系统不那么完善)。


首先,曾经有过一篇是写的hibernate sql语句提交顺序。


Hibernate数据库操作的顺序save(insert),update、delete 事务管理
http://bbs.vpigirl.com/forum.php?mod=viewthread&tid=291&fromuid=2
(出处: 心惊变 回忆的路上,时间变得好慢!)


其中有一句话是关键:


1 NEVEL
已经废弃了,被MANUAL取代了(会开启只读事务,同时会自动优化查询执行顺序)



这个模式会开启sql执行优化,所以会出现 先写的sql后执行,后写的sql先执行,所以后面的查询无法查询出先前插入的数据。


唉~事务性要求比较高的系统,就这样。
------------------------------------------------------------------------------------


但是,这样同样存在问题,因为发现Spring事务和Hibernate事务并不是一回事。


<filter>        <filter-name>openSessionInViewFilter</filter-name>        <filter-class>                org.springframework.orm.hibernate3.support.OpenSessionInViewFilter        </filter-class>        <init-param>                <param-name>singleSession</param-name>                <param-value>true</param-value>                <param-name>flushMode</param-name>                <param-value>AUTO</param-value>        </init-param></filter>






这里的配置,在使用getHibernateTemplate().getSessionFactory().getCurrentSession().getFlushMode()的时候,会看到,session的模式是变化了。 模式为AUTO。
但是使用getHibernateTemplate().getFlushMode()时,看到的结果是 1 。这个1和 Hibernate 的不一样:




Field Summary
static int
FLUSH_ALWAYS 
          Flushing before every query statement is rarely necessary.
static int
FLUSH_AUTO 
          Automatic flushing is the default mode for a Hibernate Session.
static int
FLUSH_COMMIT 
          Flushing at commit only is intended for units of work where no intermediate flushing is desired, not even for find operations that might involve already modified instances.
static int
FLUSH_EAGER 
          Eager flushing leads to immediate synchronization with the database, even if in a transaction.
static int
FLUSH_NEVER 
          Never flush is a good strategy for read-only units of work.


以上是Spring中的5种模式。
org.springframework.orm.hibernate3.HibernateTemplate 继承自 org.springframework.orm.hibernate3.HibernateAccessor


此类中默认设置private int flushMode = 1;
它还有一个方法  


protected void flushIfNecessary(Session session, boolean existingTransaction)  throws HibernateException{  if ((getFlushMode() == 2) || ((!existingTransaction) && (getFlushMode() != 0))) {    this.logger.debug("Eagerly flushing Hibernate session");    session.flush();  }}





据说使用了 OpenSessionInViewFilter 后,Spring 会认为有事务存在。即 existingTransaction == true 


所以,只有两种方法:第一、在 Spring 的 FlushMode 模式 为 2 的时候,才能刷入数据库(PS:刷入数据库不等于提交事务,只有session.commit()的时候才是提交事务,session.flush()只是让数据库在这个会话中执行一下sql,在这个会话中可以查询到数据,没有提交事务前,其它会话查询不到的)第二、手动刷入数据库


鉴于这并不是很常见的问题,我选择手动刷入数据库。


另外,我们同事给了另外的意见。


因为我两个保存,第一个是使用hibernate存储对象,第二个是sql语句直接插入,所以会先执行第二个sql。


同事建议我,要么都写成对象存储,要么都写成sql存储,就这会有问题。


但是想想,无论如何,都是要把第一步的数据插入到数据库,第二步需要使用。我当然选择最简单的方法了。


这几天工作好没有激情。


祝所有人新年快乐!
0 0