Spring事务和事务传播机制

目录

事务定义

为什么要用事务

Spring中事务的实现

编程式事务

 声明式事务

 @Transactional

 @Transactional的作用范围

 @Transactional的参数说明

Spring事务的隔离级别

 @Transactional的注意事项

 Spring里事务失效的场景

Spring事务的传播机制

嵌套事务和加入事务的区别


事务定义

将一组操作封装成一个执行单元(封装到一起),要么全部成功,要么全部失败.

为什么要用事务

比如转账分为两个操作,A账户-100,B账户+100,如果第一步成功了,第二部失败了,那么A账户就会平白无故的减去100,使用事务就可以解决这个问题,要么一起成功,失败就回滚.

Spring中事务的实现

Spring中的事务操作分为两类:编程式事务(手动写代码操作事务)和声明式事务(利用注解自动开启和提交事务).

编程式事务

spring编程式事务有3个重要步骤:开启事务(获取事务),提交事务,回滚事务.

SpringBoot内置了两个对象,DataSourceTransactionManager ⽤来获取事务(开启事务)、提交或

回滚事务的, TransactionDefinition是事务的属性,在获取事务的时候将TransactionDefinition传递进
去从而获得一个事务TransactionStatus.
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    //编程式事务
    //操作事务的时候,需要通过事务管理器
    @Autowired
    private DataSourceTransactionManager transactionManager;
    //事务的属性,要求通过事务管理器transactionManager得到事务transactionStatus的时候
    // 需要传递事务的属性transactionDefinition
    @Autowired
    private TransactionDefinition transactionDefinition;
    @RequestMapping("/del")
    public int del(Integer id){
        if (id!=null && id>0){
            //1.开启事务
            TransactionStatus transactionStatus =
                    transactionManager.getTransaction(transactionDefinition);
            //业务操作,删除用户
            int result = userService.del(id);
            System.out.println("删除: " + result);
            //2.提交事务或者回滚事务
            //transactionManager.commit(transactionStatus); //提交事务
            transactionManager.rollback(transactionStatus); //回滚事务
            return result;
        }
        return 0;
    }
}

 声明式事务

声明式事务的实现很简单,只需要在需要开启事务的方法上添加@Transactional注解即可,无需手动开启事务和提交事务,进入方法时自动开启事务,方法执行完会自动提交事务,如果中途发生了没有处理的异常就会自动回滚事务.

@RestController
@RequestMapping("/user2")
public class UserController2 {
    @Autowired
    private UserService userService;

    @RequestMapping("/del2")
    @Transactional
    public int del(Integer id){
        if (id==null && id<=0){
            return 0;
        }
        return userService.del(id);
    }
}

 @Transactional

 @Transactional的作用范围

 @Transactional可以用来修饰方法或者类.

修饰方法的时候,需要注意的是,只能应用到public方法上,否则不生效.

修饰类的时候,表明该注解对该类中所有的public方法都生效.


 @Transactional的参数说明

Spring事务和事务传播机制_第1张图片

timeout默认是-1,表示没有超时时间.

只读事务比普通事务的执行效率要高,如果只有读操作,可以把readOnly设置成true.


Spring事务的隔离级别

Spring事务和事务传播机制_第2张图片 

默认就是以连接的数据库的隔离级别为准.

Spring事务和事务传播机制_第3张图片 


 @Transactional的注意事项

  @Transactional在异常被捕获的情况下(出现了异常并添加了try-catch语句),不进行事务的自动回滚,导致业务执行出错.

解决方案:

1.将异常抛出去,让框架感知到异常,如果框架感知到异常之后,它也会自动回滚事务.

Spring事务和事务传播机制_第4张图片

2. 通过代码的方式手动回滚事务

拿到当前的事务并进行回滚.

Spring事务和事务传播机制_第5张图片


 Spring里事务失效的场景

  1. 非public修饰的方法
  2. timeout设置过小,在 @Transactional里设置了一个较小的超时时间,如果方法本身的执行时间超过了timeout超时时间,那么就会导致本来应该正常插入数据的方法执行失败,事务也会失效.
  3. 代码中使用try/catch处理异常
  4. 调用类内部的 @Transactional方法,当调用类内部的 @Transactional修饰的方法时,事务也会失效.
  5. 数据库不支持事务,我们程序中的 @Transactional 只是给调用的数据库发送了:开始事务、提交事务、回滚事务的指令,但是如果数据库本身不支持事务,比如 MySQL 中设置了使用 MyISAM 引擎,那么它本身是不支持事务的,这种情况下,即使在程序中添加了 @Transactional 注解,那么依然不会有事务的行为.

Spring事务的传播机制

Spring 事务传播机制定义了多个包含了事务的⽅法,相互调⽤时,事务是如何在这些⽅法间进⾏传递的。

为什么需要事务传播机制

事务隔离级别保证多个并发的事务执行是可控性的,而事务传播机制是保证一个事务在多个调用方法间的可控性.

Spring事务和事务传播机制_第6张图片

 

Spring事务和事务传播机制_第7张图片

 

Spring事务和事务传播机制_第8张图片 

嵌套事务和加入事务的区别

整个事务如果全部执行成功,二者的结果都是一样的.如果事务执行到一半失败了,那么加入事务是整个事务会全部回滚;而嵌套事务实现的是局部回滚,不会影响上一个方法的执行结果.嵌套事务只所以能够实现部分事务的回滚,是因为事务中有⼀个保存点(savepoint)的概念,嵌套事务进⼊之后相当于新建了⼀个保存点,⽽回滚时只回滚到当前保存点,因此之前的事务是不受影响的.


你可能感兴趣的:(spring,java,后端)