Spring 事务注解

一、Mysql事务特性与隔离级别

ACID特性

1.原子性(Atomicity)

是指事务是一个不可分割的单位,事务中的操作要么全部执行成功,要么全部执行失败

2.一致性(Consistency)

是指事务中的最后的状态为预期的状态,从一个一致性状态变成另一个一致性的状态

3.隔离性(Isolation)

是指事务中一个事务的操作不能被另一个事务操作所影响,多个并发事务要相互隔离

4.持久性

是指事务成功提交后,对数据操作的结果是永久性的

事务的隔离级别 由低到高

Mysql默认隔离级别是可重复读(repeatable-read)

事务隔离级别脏读不可重复度幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)
串行化(serializable)

二、Spring事务注解@Transactional的使用

1.定义事务的数据源

 @Bean
 public DataSource dataSource() {
    DruidDataSource ds = new DruidDataSource();
      ds.setDriverClassName(driver);
      ds.setUrl(url);
      ds.setUsername(userName);
      ds.setPassword(password);
      return ds;

  }

//定义事务管理器
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
    dataSourceTransactionManager.setDataSource(dataSource);
    return dataSourceTransactionManager;
}

2.springConfig开启事务注解

@EnableTransactionManagement
public class SpringConfig {}

3.使用@Transactional注解

(1)定义在类上 表示该类中所有的public方法都使用事务
(2)定义在方法上 表示该方法使用事务注意非public修饰符的方法事务会失效

三、@Transactional注解配置项

属性类型描述
valueString可以指定使用的事务管理器
propagationenum: Propagation指定事务的传播行为
readOnlyboolean指定事务是否只读
isolationenum: Isolation指定事务的隔离级别
timeOutint(秒)指定事务的超时时间
rollbackForClass对象数组,必须继承自Throwable指定事务回滚的异常类
rollbackForClassName类名数组,必须继承自Throwable指定事务回滚的异常类名字数组
noRollbackForClass对象数组,必须继承自Throwable指定事务不回滚的异常类数组
noRollbackForClassName类名数组,必须继承自Throwable指定事务不回滚的异常类名字数组

Spring默认RuntimeException 和Error错误才会回滚事务 所以可以指定异常类型或自定义异常类回滚事务

在这里插入图片描述

(1)timeout 超时设置

// timeout = -1 表示永不超时 
// 30为默认时间
@Transactional(timeout = 30)

(2)readOnly 事务是否只读

// 默认false

// 在不需要事务的方法中可以定义为true
@Transactional(readOnly = false)

(3)isolation 事务的隔离级别配置


// MYSQL: 默认为REPEATABLE_READ级别 

// 读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_UNCOMMITTED)

// 读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.READ_COMMITTED)

// 可重复读(会出现幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)

// 串行化
@Transactional(isolation = Isolation.SERIALIZABLE)

(4)rollbackFor 触发事务回滚的异常类型,可以指定多个

// 如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚
@Transactional(rollbackFor=Exception.class)

(5)noRollbackFor 指定异常不回滚

// Exception异常不会回滚。runtimeException会回滚事务
@Transactional(rollbackFor=Exception.class)

(6)propagation 事务的传播行为

// 如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.REQUIRED)

// 不为这个方法开启事务
@Transactional(propagation=Propagation.NOT_SUPPORTED)

// 不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕后继续执行老的事务
@Transactional(propagation=Propagation.REQUIRES_NEW) 

// 必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.MANDATORY) 

// 必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.NEVER) 

// 如果其他bean调用这个方法,在其他bean中声明事务那就用事务,如果其他bean没有声明事务,那就不用事务
@Transactional(propagation=Propagation.SUPPORTS)

四、事务失效的几种场景

(1)@Transactional 应用在非 public 修饰的方法上

(2)@Transactional 注解属性 propagation 设置错误

TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

(3)@Transactional 注解属性 rollbackFor 指定异常类设置错误

(4)@Transactional 注解属性 rollbackFor 指定异常类设置错误

1.开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方

@GetMapping("/test")
private Integer A() throws Exception {
    CityInfoDict cityInfoDict = new CityInfoDict();
    cityInfoDict.setCityName("2");
    /**
     * B 插入字段为 3的数据
     */
    this.insertB();
    /**
     * A 插入字段为 2的数据
     */
    int insert = cityInfoDictMapper.insert(cityInfoDict);

    return insert;
}

 @Transactional()
 public Integer insertB() throws Exception {
     CityInfoDict cityInfoDict = new CityInfoDict();
     cityInfoDict.setCityName("3");
     cityInfoDict.setParentCityId(3);

     return cityInfoDictMapper.insert(cityInfoDict);
 }

(5)异常被你的 catch“吃了”导致@Transactional失效

@Transactional
private Integer A() throws Exception {
     try {
         /**
          * B 插入字段为 3的数据
          */
         b.insertB();
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

A方法调用B方法 B方法抛出异常被A捕获了,事务不能回滚

(6)数据库不是Innodb引擎, 不支持事务

借鉴:
事务异常

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值