启用事务配置
使用@Transaction注解方式配置,
在启动主类添加注解:@EnableTransactionManagement
在对应的方法上或者类上加上@Transaction就会自动接入到spring的事物中,让spring管理。
Springboot中使用 @Transaction注解不生效的情况
- 情况1:
遇到非检测异常时,事务不开启,也无法回滚。
原因:因为Spring的默认的事务规则是遇到运行异常(RuntimeException)和程序错误(Error)才会回滚。如果想针对非检测异常进行事务回滚,可以在@Transactional 注解里使用rollbackFor 属性明确指定异常。
@Override
@Transactional
public void save2(ArBill bill) throws SQLTimeoutException {
ArBill save = billRepository.save(bill);
System.out.println(save.getId());
if ("01".equals(save.getBillStatus())) {
throw new SQLTimeoutException("lala");
}
}
@Transactional
public void save3(ArBill bill) {
ArBill save = billRepository.save(bill);
System.out.println(save.getId());
if ("01".equals(save.getBillStatus())) {
throw new ArBillException("lala");
}
}
- 情况2: 在业务层捕捉异常后,发现事务不生效。
原因:在业务层手工捕捉并处理了异常(try…catch)等于把异常“吃”掉了,Spring自然不知道这里有错,更不会主动去回滚数据。推荐做法是在业务层统一抛出异常,然后在控制层统一处理
- 情况3 :注解到protected可见度的方法上,事务不生效
原因:@Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
- 情况4
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用
@Transactional注解进行修饰。
ps :
需要注意的是调用的方法是否标记为@Transaction
A:如果标记了, 也是处于spring管理下的,那么也是生效的,
B:如果是一个普通方法,调用标记了@Transaction事务注解, 那么不生效.
@Override
public void save8(ArBill bill) {
save8son(bill);
}
@Transactional
private void save8son(ArBill bill){
arBillTestRepository.deleteByBillIda("123");
}
- 情况 5 : 数据库配置可能会影响事务
例如 Mysql 数据库引擎 MyISAM 和 innodbj
MyISAM存储引擎的特点是:表级锁、不支持事务和全文索引
InnoDB存储引擎的特点是:行级锁、事务安全(ACID兼容)、支持外键查询表的引擎
show table status;
80
@Transactional 注解的属性介绍
value 和 transactionManager 属性
它们两个是一样的意思。当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器。
propagation 属性
事务的传播行为,默认值为 Propagation.REQUIRED。
可选的值有:
-
Propagation.REQUIRED
如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。
-
Propagation.SUPPORTS
如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
-
Propagation.MANDATORY
如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
-
Propagation.REQUIRES_NEW
重新创建一个新的事务,如果当前存在事务,暂停当前的事务。
-
Propagation.NOT_SUPPORTED
以非事务的方式运行,如果当前存在事务,暂停当前的事务。
-
Propagation.NEVER
以非事务的方式运行,如果当前存在事务,则抛出异常。
-
Propagation.NESTED
和 Propagation.REQUIRED 效果一样。
isolation 属性
事务的隔离级别,默认值为 Isolation.DEFAULT。
- DEFAULT :表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是: READ_COMMITTED 。
- READ_UNCOMMITTED :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
- READ_COMMITTED :该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
- REPEATABLE_READ :该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
- SERIALIZABLE :所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
timeout 属性
事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
readOnly 属性
指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
rollbackFor 属性
用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。
noRollbackFor 属性
抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。