springboot--事务的使用

@Transactional原理

        事务是一些sql语句对数据库操作的集合,因此如果在一个Java方法里涉及了对数据库的操作,业务需要的话我们就可以考虑把这些操作作为一个事务。通过在方法上加个@Transactional(....)注解即可。

        如:

public class Transaction {

    @Transactional(....)
    public void doSomething() {
        .....
    }
}

对于springboot,加了@Transactional的方法其实是这样执行的:

BEGIN TRANSACTION;
try{
    doSomething();      //执行方法
    COMMIT;
}catch(Throwable t){
    if(t是该回滚的异常)
        ROLLBACK;
     else 
        COMMIT;
}

知道了注解的原理就好办了,接下来只需了解这个注解的参数即可应付很多业务场景。

控制回滚参数

        rollbackFor = xx.class 表示抛出的异常是xx类及其子类,事务会回滚; noRollbackFor = yy.class表示抛出异常是yy类或其子类,事务不会回滚。在@Transactional(rollbackFor = xx.class , noRollbackFor = yy.class)中,使用了控制回滚的参数。

 

 

 catch到异常具体怎么办?根据以上几点规则,判断异常类型与参数中声明的类型关系决定。

事务组合控制参数

        当一个作为事务的方法调用另一个作为事务的方法,它们之间的关系如何?这可以通过propagation参数控制。规则如下:

 

 

 例如:

public class Transaction {

    @Autowired
    TransactionB b;
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
       // 插入 id=1 的记录
        b.methodB();
    }
}

class TransactionB {

     @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // 插入 id=2 的记录
    }
}

1.methodB的注解参数  propagation = Propagation.REQUIRED 表示二者合并为同一个事务,id = 1,id = 2的记录只可能同时插入成功,或者同时插入失败。

2.若methodB的注解参数  propagation = Propagation.REQUIRES_NEW 表示methodB的事务会被作为一个新事务,两个事务之间没有约束关系,是独立的。                      id = 1,id = 2的记录可能同时插入失败/成功,也可能成功插入某一条。

3.若methodB的注解参数  propagation = Propagation.NESTED,表示methodB的事务是嵌套在methodA的事务中的,嵌套事务成功需要依赖主事务成功。反过来嵌套     事务则不会决定主事务的成功。即id = 1插入成功(主),id = 2(嵌套)不一定插入成功;id = 1插入失败,id = 2则一定插入失败。

事务隔离级别控制参数

        事务隔离级别的设置很简单,直接@Transactional(isolation = xx)就可以指定方法中事务的隔离级别,隔离级别从低到高有:READ_UNCOMMITTED(读未提交)、READ_COMMITTED(读已提交)、REPEATABLE_READ(可重复读)、SERIALIZABLE(串行化)。具体隔离级别以及每个隔离级别的意义这里就不讲了。

事务超时控制参数

        timeout参数表示事务的时间限制,超出指定时间则抛出TransactionTimeOut异常。使用如下:

 

 @Transactional(timeout = 5) //
    public void methodA() {     ---事务开始则计时开始
        // 1 执行java代码         ---纳入计时
        // 2 执行sql              ---执行前检查是否超时
        // 3 执行java代码         ---纳入计时
        // 4 执行sql              --执行前检查是否超时
        // 5 执行java代码         ---由于sql执行完毕,事务已提交,这里不被纳入计时
    }

 

注意:只有每次执行sql会检查是否超时,如果执行这个sql前没超时,就算这个sql执行了20s也不会抛出TransactionTimeOut异常。

 

posted on 2019-09-03 18:21  千山万水楼外楼  阅读(303)  评论(0编辑  收藏  举报

导航