Spring中的事务

Spring事务的原理:

Spring中对事务支持实际上就是数据库对事务的支持,它依赖于数据库对事务性,只是利用Spring中AOP进行了事务的封装,我们传统的JDBC如果要开启事务一般如下:

  1. 加载驱动
  2. 获取连接对象Connection con = DriverManager.getConnection()
  3. con.setAutoCommit(false);
  4. 预处理sql语句preparestatment
  5. 设置占位符
  6. 执行sql语句并得到查询或者更新、结果
  7. 提交事务/回滚事务 con.commit() / con.rollback();
  8. 关闭连接(释放资源)
    Spring其实就是通过配置,生成代理对象,动态的为我们执行了第3、7步

Spring中事务的使用:

1.SpringBoot中使用事务非常方便,直接在启动类上添加注解@EnableTransactionManagement,在需要事务管理的方法上添加@Transactional即可
2.传统的SSM中则需要配置:
xml文件中:

<!--开启注解的方式--> 
<tx:annotation-driven transaction-manager="transactioManager" />

方法上使用@Transactional注解:

@Transactional(isolation=Isolation.DEFAULT)
public void fun(){
	dao.add();
	dao.udpate();
}

Spring支持的事务隔离等级

注解@Transactional里的isolation属性为设置的事务隔离级别,Spring中支持五种配置:

  • TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
  • TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
  • TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  • TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

第一种配置表示使用和数据库一致的事务隔离级别,其他四种则分别对应了数据库中四种隔离级别:读未提交、读已提交、可重复读、串行化;

Spring中的传播行为:

Spring中规定了一些在嵌套事务的场景的配置,一共有7种:

  • TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
  • TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED

但一般我们只使用前两个,假设外层事务 Service A 的 Method A() 调用 内层Service B 的 Method B()

  • 假设ServiceB.methodB() 的事务级别定义为 PROPAGATION_REQUIRED,那么执行 ServiceA.methodA() 的时候spring已经起了事务,这时调用 ServiceB.methodB(),ServiceB.methodB() 看到自己已经运行在 ServiceA.methodA() 的事务内部,就不再起新的事务。
    假如 ServiceB.methodB() 运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
    这样,在 ServiceA.methodA() 或者在 ServiceB.methodB() 内的任何地方出现异常,事务都会被回滚。
  • 假设ServiceB.methodB() 的事务级别为 PROPAGATION_SUPPORTS,那么当执行到ServiceB.methodB()时,如果发现ServiceA.methodA()已经开启了一个事务,则加入当前的事务,如果发现ServiceA.methodA()没有开启事务,则自己也不开启事务。这种时候,内部方法的事务性完全依赖于最外层的事务。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值