加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Spring+Hibernaet+MySQL事务处理中遇到问题及处理

发布时间:2021-12-10 17:29:30 所属栏目:PHP教程 来源:互联网
导读:spring的事务处理本来就是依赖于底层的实现,比如hibernate及数据库本身。所以,当使用MySQL数据库时,首先要确定的是,所操作的对象表是innodb格式的。 1. read-only方法中进行更新或插入操作时,并不总报错 在service层的方法中定义了事务,并且在spring配
spring的事务处理本来就是依赖于底层的实现,比如hibernate及数据库本身。所以,当使用MySQL数据库时,首先要确定的是,所操作的对象表是innodb格式的。
 
1. read-only方法中进行更新或插入操作时,并不总报错
 
在service层的方法中定义了事务,并且在spring配置文件中定义了如下的传播方式:
 
<tx:attributes >
 
  <tx:method name="save*" propagation="REQUIRED" />
 
  <tx:method name="update*" propagation="REQUIRED" />
 
  <tx:method name="*" read-only= "true" />
 
 </tx:attributes>
 
假设有一个实体名称为User,则如果在在service的一个方法中想保存或更新它,而这个方法又忘记了以save或update开头,就会导致一些莫名其妙的事情发生,有时会报错(这可以理解),但有时又不会报错,动作却没有执行,反复观察,发现以下规律:
 
当更新user的操作时,即此时user的主键不为null时,调用Dao中的Hibernate的saveOrUpdate方法时,程序不报错,但修改动作未起作用;
 
当进行插入操作时,此时user的主键为Null(库中的主键采用自增),此时调用saveOrUpdate方法时,程序报错:Connection is read-only. Queries leading to data modification are not allowed.
 
2. 在事务方法中抛出异常,并不总回滚
 
一个事务方法中:
 
xxxDao.save(user);
 
.....
 
throw new Exception("要求回滚");
 
抛出异常后,期望事务能回滚,观察数据库,却发现改变已写进持久层了。
 
原因是这样的:Spring、EJB的声明式事务默认情况下都是在抛出unchecked exception后才会触发事务的回滚。Exception这个异常是checked异常,所以无法触发回滚事件,如果换成抛出RuntimeException异常,则程序运行就符合预期了。
 
3. 事务方法嵌套调用
 
在一个service中,用一个read-only方法调用非read-only方法,则发现整个调用都read-only了。
 
这是因为:service内部方法间调用,被调用方法设定的事务行为将会失效,事务行为由最外层方法设置的事务行为控制。
 
4. 事务回滚未提交,并不表示对底层数据库没有任何影响。
 
下面的代码:
 
xxxDao.save(user);
Integer userId = user.getId();
.....
throw new RuntimeException("要求回滚");
 
事务会成功回滚,数据表中也未插入新的记录。但观察发现,userId的值也取到了,比如说userId=9800,如果再向数据库增加一条记录,则自增的id值会变成9801!
 
也就是说,虽然由于事务回滚没有向持久层插入记录,但数据表的自增字段的值已经被改变了。(这一块的机制细节没功夫研究了,有人了解的话,告诉我一下)

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读