Spring事务

Spring事务

    • 一、什么是事务、事务的特性、事务的隔离级别
    • 二、Spring中事务实现
      • 编程式事务:手动写代码操作事务
      • 声明式事务:使用注解自动开启和提交事务
    • 三、Spring事务隔离级别及设置方法
    • 四、Spring的事务传播机制
    • Spring事务失效的情况
    • @Transactional注解
      • 参数说明:
    • 说明

一、什么是事务、事务的特性、事务的隔离级别

事务就是逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。

事务具有四大特性(ACID),原子性(Atomomicity),一致性(Consistency),持久性(Isolation),隔离性(Durability)。不同的隔离级别总共可能产生三种问题脏读,不可重复度,幻读。

MySQL事务的隔离级别有四种read uncommited,read commited,repeatable read,serializable,MySQL默认是可重复读。读未提交三种问题都可能产生,读已提交可以解决脏读问题,但是解决不了不可重复读和幻读问题,可重复读可以解决前两种问题,串行化可以解决这三种问题。

二、Spring中事务实现

编程式事务:手动写代码操作事务

以向数据表删除记录为例

  1. 拿到JDBC事务管理器( DataSourceTransactionManager)对象
  2. 拿到事务定义(TransactionDefinition)对象
  3. 开启事务
  4. 插入数据库
  5. 提交事务/回滚事务
@RestController
@RequestMapping("/user0")
public class UserController0 {

    @Autowired
    private UserService userService;
    //1.创建JDBC事务管理器和事务定义对象
    @Autowired
    private DataSourceTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/del")
    public int del(Integer id) {
        if(id != null && id > 0) {
            //2.开启事务
            TransactionStatus transactionStatus =
                    transactionManager.getTransaction(transactionDefinition);
            //3.删除用户业务操作
            int result = userService.del(id);
            System.out.println("删除了: " + result);
            // 4.提交事务/回滚事务
//            transactionManager.commit(transactionStatus); //提交事务
            transactionManager.rollback(transactionStatus); //回滚事务
        }
        return 0;
    }
}
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public int del(Integer id){
        return userMapper.del(id);
    }
}
@Mapper
public interface UserMapper {
    int del(@Param("id")Integer id);
}
<delete id="del">
    delete from userinfo where id=#{id}
delete>

Spring事务_第1张图片

声明式事务:使用注解自动开启和提交事务

在方法/类上加@Transactinonal注解。

进入方法自动开启事务,执行完毕自动提交,发生异常自动回滚事务:

成功的情况:

@RestController
@RequestMapping("/user0")
public class UserController0 {

    @Autowired
    private UserService userService;

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

对应的mapper和xml配置不用变,还是调用对象的service里的方法。

Spring事务_第2张图片

报异常并回滚事务的情况:

这里人为加一个算数异常:

@Transactional
@RequestMapping("/del3")
public int del3(Integer id) {
    if(id == null || id <= 0) {
        return 0;
    }
    int result=0;
    result=userService.del(id);
    int num=10/0;
    System.out.println(result);
    return result;
}

Spring事务_第3张图片

三、Spring事务隔离级别及设置方法

Spring事务默认级别就是对应连接数据的默认隔离级别

Spring事务_第4张图片

和MySQL的隔离级别含义基本一模一样。

通过Transactional的isolation属性设置:

Spring事务_第5张图片

四、Spring的事务传播机制

多个事务进行嵌套调用的时,事务的执行行为叫做事务的传播机制。事务传播机制保证每个事务在多个调用方法间可控。

事务的传播机制一共分为三大类:支持当前事务,不支持当前事务和嵌套事务。

Spring事务_第6张图片

  1. 支持当前事务:以REQUIRED为例,一旦发生异常调用链上的所有事务全部回滚
  2. 不支持当前:以REQUIRED_NEW为例,
  3. 嵌套事务:嵌套事务可以回滚部分事务。(外部/主事务和内部/子事务)
    • 主事务提交成功,子事务也会被提交
    • 主事务回滚,子事务无论是否成功,一定回滚

Spring事务失效的情况

1.异常捕获处理

去掉try catch包裹

在之前的代码上边加try catch处理,再运行可以发现数据库的记录被删除,报错,事务失效

Spring事务_第7张图片

因为事务通知只有自己捕捉到了对应代码抛出的异常,才能进行回滚操作,这里如果自己处理了,事务没办法感知到。

2.非public修饰的方法

将方法设置成Public类型的

3.抛出受查异常

原因:spring默认只能回滚非受查异常。

解决办法:将@Transactional的rollbackFor属性设置为Exception.class

@Transactional注解

@Transactional使用方法:修饰类对类中所有public方法都生效,修饰方法对public方法生效。

参数说明:

参数 作用
value 当配置了多个事务管理器时,可使用该属性指定选择哪个事务管理器
transactionManager 当配置多个事务管理器,可使用该使用指定选择哪个事务管理器
propagation 事务的传播机制,默认值为Propagation.REQUIRED
isolation 事务的隔离级别,默认值为Isolation.DEFAULT
timeout 事务的超时时间,默认值为-1,如果超过该事件限制但事务还没完成,则自动回滚事务
readOnly 指定事务是否为只读事务,默认值为false
rollbackFor 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型
rollbackForClassName 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型(字符串类型)
noRollbackFor 不回滚抛出异常
noRollbackForClassName 不回滚抛出异常(字符串类型)

说明

实际开发中,绝大部分时候会使用声明式事务,毕竟只需要加一个注解就可以实现想要的功能。

你可能感兴趣的:(JAVA,EE,spring,java,事务)