Spring Boot中的事务

什么是事务

事务可以理解为一项不可中断的连续任务, 在完成任务的过程中会随着进程获得奖励(写入数据库), 如果中间产生问题(抛异常), 任务就会失败, 所有奖励也会消失(回滚)

在Spring Boot中我们可以很方便的使用@Transactional注解完成事务

如何使用

@Transactional可应用于方法和类上, 我们只需要在需要事务的合适位置加入它即可

过多详细的配置不再赘述, 可以参考这篇文章

补充如下两点:

规定事务的异常

在设计到自定义异常回滚时, 我们可以这样使用:

@Transactional(rollbackFor = {MyException.class})
public class MyService {
    业务代码...
}
复制代码

其中MyException为我的自定义异常, 只有在捕获到这种异常时, 事务才会触发回滚

只读模式

@Transactional(readOnly=true)

当设置事务为只读时, Hibernate会为其提供Session方面的一些优化手段

各种可能出现的数据读取错误

今天想要记录的是关于各种”读”的

数据读取错误的类型有: 脏读/不可重复读/幻读

我们可以通过设置@Transactional的isolation, 即隔离级别, 来防止出现错误情况

脏读

  • 操作人A: 修改t_user中id为1的用户, 将它的sex设置为-99, 但因为网络超时, 操作失败
  • 操作人B: 读取t_user中id为1的用户, 发现它的sex是错误的-99, 但检查数据库发现sex为1

此时对于操作人B而言, 就读取到了”脏”的数据, 因为-99是未完成的事务, 实际id为1的用户性别并没有发生变化

TransactionDefinition.ISOLATION_READ_COMMITTED可以解决这个问题

不可重复度

  • 操作人A: 修改t_user中id为1的用户, 将它的sex设置为-99, 操作成功
  • 操作人B: 需要快速确认两次id为1的用户性别, 发现第一次是1, 第二次是99

此时对于操作人B而言, 就发生了不可重复读, 即在同一操作中读取两次数据, 两次数据结果不一致

ransactionDefinition.ISOLATION_REPEATABLE_READ可以防止不可重复度, 同时也可以防止脏读哦

幻读

  • 操作人A: 修改t_user中的全部数据, 将它们的sex设置为-99
  • 操作人B: 在t_user中插入一条新用户, 名为”天下无敌”

此时对于操作人A来说, 就如同产生了幻觉, 刚刚明明把所有人的性别都设置为了-99, 但”天下无敌”的性别竟然还是3,他仿佛逃脱了系统的限制

TransactionDefinition.ISOLATION_SERIALIZABLE可以防止幻读, 同时防止不可重复读和脏读, 但是, 此设置会严重影响性能

总结

操作人B挺惨的, 出事的总是他

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享