最近项目突然出了点问题,然后发现用Service层下面的一个类的一个方法里的事务居然没有回滚。然后自己写了一个测试方法经过了N次测试都是不回滚。以下是测试方法的一部分:
@Transactional(propagation =Propagation.REQUIRED,rollbackFor=RuntimeException.class) public String getOnLineNum(String securecrt){
History his=new History();
his.setItem("123"); //此处特意设置一个超出字段长度使其出错
Ludan lu=new Ludan();
lu.setRoomName("33333333333333333"); historyDao.save(his);
ludanDao.save(lu); return "123";
}
以上代码经过许多次的测试都是会把history表存入记录,但是ludan报错存入不了,这样相当于事务并没有回滚。
如下是Spring的部分配置:
<!-- spring 事务管理 start-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean> <!-- 声明使用注解式事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
一。 如上就是问题,然后经过大范围的查阅以及搜索,最后总结了几点Spring事务不回滚的原因:
1.你自己捕获异常了,没有抛出去让Spring知道。
2.没有正确配置Spring中的事务。
3.Service层次问题,即一些逻辑问题。
4.MySQL不支持事务。
二。解决办法
这里重点讲解一下上线的第四种原因的解决办法,这也是本人项目中遇到的问题。即MYSQL默认的数据库模式是MyISAM,而这个模式是不支持事务的,并且在安装mysql的时候默认的数据库模式就是MyISAM。在mysql里输入:show engines;就会看到如下的画面:
可以看到只有InnoDB才支持事务。因此要实现mysql的事务必须先把mysql数据库模式转换成InnoDB。
具体方法如下:
1.打开根目录下得my.ini文件,在[mysqld]下加入:
default-storage-engine=INNODB
如果有skip-innodb,那就把这行注掉即可。
2.重启mysql服务
3.再次进入mysql,输入:show engines;就可以看到默认的数据库模式已经是INNODB了;
4.原来存在的表则需要删除以后再重新建一个就是INNODB的了,如果不想删除,那就进入mysql,更新一下表引擎就可以了
执行:alter table 表名 ENGINE=InnoDB;
然后在执行:show table status from 数据库名 where name='表名';就可以查看状态了
5.再次测试上面的代码就发现事务回滚了。
三。总结
对于这个自己遇到的问题可能是大部分人都遇到过的问题吧,也算是自己的经验不足造成的,因此记录下来方便一些像我一样走在程序的路上的朋友们,希望能对大家有一些帮助,也同时做一个自己的工作记录吧,以后也可以回来再次审查。