spring事务、事务的隔离级别、事务失效

spring事务是基于jdbc实现的;

spring提供2种开启事务方式,一种是编程式,一种是注解方式@Transactional

只需要在某个方法上加上@Transactional注解即可;添加了@Transactional注解时,spring会把事务的自动提交设为false,当业务逻辑方法出错时就会回滚;

可以在@Transactional注解的rollbaackFor属性中配置 出现哪些异常 才会回滚,默认会对RuntimeExecption和Error进行回滚(前提是这个异常不能捕获catch);

@Transactional(rollbackFor = Exception.class)


事务隔离级别

mysql默认的事务隔离级别时rc,spring事务默认是rr;
如果数据库和spring都配置了事务隔离机制,那么最终以spring为准;
如果spring配置的事务隔离机制数据库不支持,那么以具体的数据库为准;


事务的传播机制

https://blog.csdn.net/yuanlaishini2010/article/details/45792069

ServiceA {
     void methodA() {
         ServiceB.methodB();
         // int i=1/0;
     }
}

ServiceB {
     void methodB() {
        do samething
     }
}

PROPAGATION_REQUIRED

PROPAGATION_REQUIRED(默认):支持当前事务,如果当前没有事务(不在另一个事务里),就新建一个事务。

如果a方法没有事务,b有事务,a方法出现异常(不是b方法里出现的异常),不会回滚;
如果a、b方法都有事务,a调用b方法,b就不会起事务(即,b支持当前a的事务),a、b无论哪个发生异常,都将回滚;

PROPAGATION_SUPPORTS

PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务(不在另一个事务中),就以非事务方式执行。

a方法没有事务,b方法有事务,a调用b,则b也不用事务(都以非事务运行); 
如果a、b方法都有事务,a调用b方法,b就不会起事务(即b,支持当前a的事务),a、b无论哪个发生异常,都将回滚;

PROPAGATION_MANDATORY

PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

如果a、b方法都有事务,a调用b方法,b就不会起事务(即,b支持当前a的事务),a、b无论哪个发生异常,都将回滚;  
如果a方法没有事务,b方法有事务,a调用b则抛异常;  

PROPAGATION_REQUIRES_NEW

PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。 

如果a、b都有事务,a调用b时,a的事务先被挂起 并为b新建一个事务,等到b的事务完成后,a事务继续执行,即a和b各自运行各自的事务;
注意,如果a出现异常,b的事务已提交(b没有异常),a会回滚,b不会回滚;

PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。

不能在事务中运行。如果a的事务级别是PROPAGATION_REQUIRED, 而b的事务级别是PROPAGATION_NEVER ,那么b就要抛出异常了。 

PROPAGATION_NESTED

PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 潜套事务开始执行时,  它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.  

事务失效

https://www.cnblogs.com/shijianchuzhenzhi/p/13237571.html

类没有被Spring管理

// @Service
public class OrderServiceImpl implements OrderService {   
 @Transactional    
public void updateOrder(Order order) {       
 // do samething 
  }
}

把@Service 注解注释掉,这个类就不会被 Spring 管理了。


方法不是 public的 – 该异常一般情况都会被编译器识别


自身this调用

@Service
public class OrderServiceImpl implements OrderService {
    public void a() {
        b();    //this.b();自身调用,没有走spring的代理类;
    }
    
    @Transactional
    public void b() {
        // do samething;
    }
}

a方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的b 方法,发生异常时,b方法的事务不生效,不会回滚;


因为,spring的事务实现是使用了代理类来实现,这里其实是this.b();


在a方法上也添加事务,可以使事务生效;

或者,使用让spring的代理类

@Service
public class TestService {

    @Autowired
    private TestService testService;
    
    /**
     * 这里调用methodB() 的事务将会生效
     */
    public void methodA(){
        testService.methodB();  //testService是spring代理的;
    }
    @Transactional
    public void methodB(){

    }

异常被捕获

@Service
public class OrderServiceImpl implements OrderService {
    @Transactional
    public void a(Order order) {
        try {
            // update order;
         }catch (Exception e){
            //do something;
        }
    }
}

出现异常时,异常被catch到,导致a方法的事务不生效,不会回滚;

解决方法,catch到后,再通过throw抛出异常;

@Service
public class OrderServiceImpl implements OrderService {
    @Transactional
    public void a(Order order) {
        try {
            // update order;
         }catch (Exception e){
            //do something;
            throw e;
        }
    }
}

抛出异常类型不对

@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
           
        } catch {
            throw new Exception("更新错误");
        }
    }
}

这样事务也是不生效的,因为默认回滚的是:RuntimeException。

如果想触发其他异常的回滚,需要在注解上配置一下,
如:@Transactional(rollbackFor = Exception.class)


传播类型不支持事务


数据库本身不支持事务

例如MyIASM引擎;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值