0
点赞
收藏
分享

微信扫一扫

CentOS-7安装grafana

zidea 2024-04-29 阅读 43
springjava

spring 事务有两种 注解型事务和编程式事务。

事务不生效

1.同一个Service中的方法调用(编程式事务无此问题)
2. 多线程调用
3. 未被spring管理(类未加@Service注解)
4. 数据库表不支持事务
5. 项目未开启事务(springboot 项目 默认开启事务)
6. 出现的异常被java代码捕获到了,而没有被事务获取到异常

注解型事务 @Transactional (简单的场景可以使用)

在Spring中对于事务的传播行为定义了七种类型分别是:

(重要)REQUIRED(Spring默认的事务传播类型)

如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务

serviceA中
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
    A(a1);  //调用A入参a1  向A表插入数据
    service.testB();    //调用另外一个serviceB 的 testB方法
}

serviceB中
@Transactional(propagation = Propagation.REQUIRED)
public void testB(){
    B(b1);  //调用B入参b1 向B表插入数据
    throw Exception;     //发生异常抛出
    B(b2);  //调用B入参b2 向B表插入数据
}

此时 因为 testB() 发生异常 并且 事务类型为 required类型 是属于同一个事务的,即A表和B表都不会插入数据,同一事物发生异常则回滚。

如果去掉 serviceA中 的 @Transactional(propagation = Propagation.REQUIRED)
则是testB()方法具有事务性,发生异常后无任何数据插入,而testA() 无事务 A表中有数据插入

SUPPORTS

当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行

serviceA中
public void testMain(){
    A(a1);  //调用A入参a1  向A表插入数据
    service.testB();    //调用另外一个serviceB 的 testB方法
}

serviceB中
@Transactional(propagation = Propagation.SUPPORTS)
public void testB(){
    B(b1);  //调用B入参b1 向B表插入数据
    throw Exception;     //发生异常抛出
    B(b2);  //调用B入参b2 向B表插入数据
}

这种情况下,执行testMain的最终结果就是,a1,b1存入数据库,b2没有存入数据库。由于testMain没有声明事务,且testB的事务传播行为是SUPPORTS,所以执行testB时就是没有事务的(如果当前没有事务,就以非事务方法执行),则在testB抛出异常时也不会发生回滚,所以最终结果就是a1和b1存储成功,b2没有存储。

那么当我们在testMain上声明事务且使用REQUIRED传播方式的时候,这个时候执行testB就满足当前存在事务,则加入当前事务,在testB抛出异常时事务就会回滚,最终结果就是a1,b1和b2都不会存储到数据库。

编程式事务

建议直接使用编程式事务,这样写出来的代码可读性好,可扩展性强,可维护性高 粒度小 可控性强,耦合度比较高,但是一定要注意spring事务的失效场景 spring事务失效场景及解决办法
例子:

Service@Resource
private TransactionTemplate transactionTemplate;

// 在需要有事务支持的代码中 一般是写入和更新 直接编程式事务写代码 例如
transactionTemplate.execute((s)->{
    // 需要事务支持的代码块  插入和更新操作
   return Boolean.TRUE;
});

事务的隔离级别

脏读幻读不可重复读详解

问题场景复现 : 一个大事务中间有多次查询数据的操作,另外一个小事务,在大事务读取数据过程中,也在操作这些数据,由此造成大事务读取出现了问题。

mysql 数据库 默认的事务隔离级别是可重复读,使用的是MVCC 解决不可重复读的问题。
具体 : 每一行数据都有一个version 在查询和修改数据的时候,都会对版本进行过滤,不符合的数据版本则不会被查询到。

参考 spring 事务传播机制详解
spring事务失效场景及解决办法
spring事务实现原理

举报

相关推荐

0 条评论