Spring整合hibernate关于控制事务的问题
2017-07-25 14:31
579 查看
今天在使用spring整合hibernate的框架中控制事务遇到数据更新未取到最新的数据,代码结构如下:
注:此处调用查询方法定义为query(),
调用更新方法定义为update(),
调用执行sql的方法定义为execute();
TableObject 对应表 dataTable;
汇总表对应 totalDataTable;
在执行上述代码后,totalDataTable表中的数据总是取的是前两次更新后数据和最后一次未更新的数据值的汇总值,原因是:
事务控制在a()方法层因此事务提交是在a()方法结束时再调用commit()方法,而hibernate机制是在事务提交时才调用flush()方法将持久化对象同步到数据库,在此之前,该持久化对象是存在缓存中的,因此在b方法中执行update时数据库中的数据是没有同步的,所以我们会读取到最后一次未更新的数据值,但是为什么前两次更新后的数据是数据库的最新值呢?这是因为hibernate的缓存中只能存在一个同一类型的持久化对象,在我们调用query()方法时,hibernate就会将上一次的保存在缓存中的持久化对象flush到数据库同步,并更新缓存中的持久化对象。
解决方法:因为我们要取到数据必须是数据库最新的值,因此我们需要在调用hibernate的save()、update()、saveOrUpdate()方法后手动的调用一次flush()方法,使缓存数据与数据库数据同步。
注:如果我们不添加事务,实际是不会出现以上问题的,因为未加事务时,hibernate默认事务提交是在dao层方法调用结束后调用flush()和commit()方法,而正是因为我们添加了事务,导致hibernate调用flush()和commit()延迟到我们控制的事务结束时,这时执行的数据库更新操作如果没有调用flush()操作实际是存在缓存中而并没有和数据库同步的。
注:此处调用查询方法定义为query(),
调用更新方法定义为update(),
调用执行sql的方法定义为execute();
TableObject 对应表 dataTable;
汇总表对应 totalDataTable;
/** *a方法循环调用b方法 */ public void a(){ //事务控制层 List<String> priNumbers = new ArrayList<String>(); priNumbers.add("1"); priNumbers.add("2"); priNumbers.add("3"); //循环修改dataTable的值 for(String priNumber : priNumbers ){ b(priNumber); } //根据dataTable的最新值修改totalDataTable的汇总值 c(); } /** *b方法查询对象并更新对象 */ public void b(String priNumber){ //根据主键查询数据库表对象obj TableObject obj = query(priNumber); . . .//修改obj的值,此处省略 //更新obj值 update(obj); } /** *c方法执行sql根据数据库表dataTable中的最新数据所有值之和修改汇总表totalDataTable的数据 */ public void c(){ execute(sql); }
在执行上述代码后,totalDataTable表中的数据总是取的是前两次更新后数据和最后一次未更新的数据值的汇总值,原因是:
事务控制在a()方法层因此事务提交是在a()方法结束时再调用commit()方法,而hibernate机制是在事务提交时才调用flush()方法将持久化对象同步到数据库,在此之前,该持久化对象是存在缓存中的,因此在b方法中执行update时数据库中的数据是没有同步的,所以我们会读取到最后一次未更新的数据值,但是为什么前两次更新后的数据是数据库的最新值呢?这是因为hibernate的缓存中只能存在一个同一类型的持久化对象,在我们调用query()方法时,hibernate就会将上一次的保存在缓存中的持久化对象flush到数据库同步,并更新缓存中的持久化对象。
解决方法:因为我们要取到数据必须是数据库最新的值,因此我们需要在调用hibernate的save()、update()、saveOrUpdate()方法后手动的调用一次flush()方法,使缓存数据与数据库数据同步。
注:如果我们不添加事务,实际是不会出现以上问题的,因为未加事务时,hibernate默认事务提交是在dao层方法调用结束后调用flush()和commit()方法,而正是因为我们添加了事务,导致hibernate调用flush()和commit()延迟到我们控制的事务结束时,这时执行的数据库更新操作如果没有调用flush()操作实际是存在缓存中而并没有和数据库同步的。
相关文章推荐
- 关于Spring整合Hibernate事务问题
- 关于spring与hibernate整合后的事务
- 关于Spring整合Hibernate中自动建表问题(hbm2ddl.auto)
- 一些关于hibernate 与 spring 事务管理的问题
- spring整合hibernate配置注解事务的相关问题
- 关于spring4和hibernate4整合,配置事务报“Cannot unwrap to requested type [javax.sql.DataSource]”错误的解决方法及心得
- 关于spring 整合 hibernate 事务不回滚
- spring与hibernate集成的session事务控制问题解析
- struts + spring + hibernate整合事务配置的问题(请教高手)
- 【Java EE 学习 53】【Spring学习第五天】【Spring整合Hibernate】【Spring整合Hibernate、Struts2】【问题:整合hibernate之后事务不能回滚】
- 关于Spring+Hibernate注解式整合问题
- 关于Struts、Spring和Hibernate整合的问题
- 关于Spring4+Hibernate4架构升级-整合的细节处理-由nested transactions not supported错误解决引申到事务嵌套问题处理
- 关于spring+hibernate整合的一些问题
- SSH整合之spring与hibernate版本问题
- 关于Spring整合发现的一些问题。
- spring和hibernate框架的整合和事务管理
- 关于Spring 声明式事务处理时,throws exception不回滚的问题
- hibernate4整合spring3事务问题
- Spring 整合 Hibernate、声明式的事务管理、HibernateTemplate(HibernateDaoSupport)