Step1:更改spring的配置文件(applicationContext.xml)
<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
Step2:修改方法,增加事务配置(controller或者service中都可以)
@Transactional一般加在类上或者类中的public方法上,当作用在类上时候,该类所有的public方法都具有该类型的事务属性。如果作用在具体的方法上面,方法上的注解会覆盖类上的注解
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public int addPlan(Plan plan) {
plan.setCreateAt(new Date());
plan.setUpdateAt(new Date());
return planMapper.add(plan);
}
Step3:测试
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public int addPlan(Plan plan) {
plan.setCreateAt(new Date());
plan.setUpdateAt(new Date());
int test = 1/0; // 手动触发异常
return planMapper.add(plan);
}
@Transactional参数说明
参数 | 说明 |
---|---|
readOnly | 是否是只读事务,true表示只读,false表示读写 |
timeout | 事务超时秒数,默认值-1表示永不超时 |
isolation | 隔离级别,例如(isolation = Isolation.READ_UNCOMMITTED) |
propagation | 事务传播行为,见表propagation说明,例如@Transactional(propagation=Propagation.REQUIRED) |
rollbackFor | 需要回滚的异常类数组,例如</br>单一异常类:@Transactional(rollbackFor=RuntimeException.class)</br> 多个异常类:@Transactional(rollbackFor={IndexOutOfBoundsException.class, OutOfMemoryException.class}) |
noRollbackFor | 不需要进行回滚的异常类数组,...... |
rollbackForClassName | 需要进行回滚的异常类名称数组,例如</br>单一异常类名称:@Transactional(rollbackForClassName="RuntimeException") </br>多个异常类名称:@Transactional(rollbackForClassName={"IndexOutOfBoundsException","OutOfMemoryException.class"}) |
noRollbackForClassName | 不需要进行回滚的异常类名称数组,...... |
propagation说明
参数 | 说明 |
---|---|
REQUIRED | 有事务,加入事务,没有新建一个 |
NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起 |
REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起 |
MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常 |
NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常 |
SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行 |
NESTED | 如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则执行与REQUIRED类似的操作 |
注意事项
- @Transactional注解起作用的方法必须是public类型
- 方法必须抛出异常
- MySQL数据库类型的选择(InnoDB)
Q:按照流程配置,但是不回滚,为什么?
这里分享一下本人遇到的一个神坑,有可能对读者有些帮助
A:如果试了各种方法都不行,再重新看下数据库的引擎类型
因为你可能并没有成功换掉db的引擎
我们知道,MyISAM并不支持事务,所以我们想要事务生效,必须修改该表的引擎为InnoDB。于是,我们在网上搜了一下如何修改引擎,于是我们执行了如下操作:alter table table_name engine=innodb;操作完之后,显示操作成功了,这样我想当然的认为该表已经成功变成了InnoDB引擎。但是,坑来了,其实可能并没有替换好。执行替换操作语句之后,请一定执行操作:show table status from mydb;查看一下表的信息,确认一下。那么,这个原因是啥呢,我又执行了语句:show engines;发现一个细节,InnoDB对应的状态是DISABLED。原来,我的InnoDB被禁用了,所以导致了上面的问题。(巨坑的MySQL,这话情况下执行语句,竟然不报错提醒)正确的操作方法如下:
- 查看数据库支持的引擎列表(如果不支持,请自行百度解决)
show engines;
- 修改引擎
alter table table_name engine=innodb;
- 查看修改结果
show table status from mydb;