当前位置:首页 > 科技  > 软件

@Transactional注解使用以及事务失效的场景

来源: 责编: 时间:2023-09-28 10:02:49 190观看
导读一、事务的本质1、何为事务管理数据库事务,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过

一、事务的本质

1、何为事务管理

数据库事务,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。hNr28资讯网——每日最新资讯28at.com

事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。hNr28资讯网——每日最新资讯28at.com

一个逻辑工作单元要成为事务,必须满足所谓的 ACID (原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位。hNr28资讯网——每日最新资讯28at.com

2、 Spring 中的事务管理

实际工作中我们更多的是结合 Spring 来做项目的这时我们要满足的情况是这种。hNr28资讯网——每日最新资讯28at.com

Controller层:  UserService:addUser();  Service层(UserService):   addUser(): insertUser()+ insertLog()  Dao层:   UserDao:insertUser();   LogDao: insertDao();

可以看出我们在 Service 中是可能调用多个 Dao 的方法来操作数据库中的数据的,我们要做的就是要保证 UserService 中的 addUser() 方法中的相关操作满足事务的要求hNr28资讯网——每日最新资讯28at.com

常见的开启 Spring 事务方式:@TransactionalhNr28资讯网——每日最新资讯28at.com

二、 @Transactional 注解

1、原理:

事务开启后,通过 AOP 机制生成一个代理数据库连接对象并将其放入 DataSource 实例的某个 DataSourceTransactionManager 相关对象容器中。在整个事务中,业务代码中所有的数据库连接都应该是同一个连接,不使用该连接的 Sql 是不会被回滚的。业务代码出现异常时会执行回滚操作hNr28资讯网——每日最新资讯28at.com

底层实现:hNr28资讯网——每日最新资讯28at.com

图片图片hNr28资讯网——每日最新资讯28at.com

2、属性介绍:

隔离级别( @Transactional ( isolation = Isolation.DEFAULT ) ): 为了解决数据库容易出现的问题,分级加锁处理策略hNr28资讯网——每日最新资讯28at.com

隔离级别
hNr28资讯网——每日最新资讯28at.com

描述
hNr28资讯网——每日最新资讯28at.com

ISOLATION_DEFAULThNr28资讯网——每日最新资讯28at.com

Spring 默认隔离级别,以连接的数据库的事务隔离级别为准;Mysql (可重复读)
hNr28资讯网——每日最新资讯28at.com

ISOLATION_READ_UNCOMMITTEDhNr28资讯网——每日最新资讯28at.com

读未提交:最低的隔离级别,其含义是允许一个事务读取另外一个事务没有提交的数据。未提交读是一种危险的隔离级别,所以一般在我们实际的开发中应用不广,但是它的优点在于并发能力高,适合那些对数据一致性没有要求而追求高并发的场景,它的最大坏处是出现脏读
hNr28资讯网——每日最新资讯28at.com

ISOLATION_READ_COMMITTEDhNr28资讯网——每日最新资讯28at.com

读已提交:是指一个事务只能读取另外一个事务已经提交的数据,不能读取未提交的数据
hNr28资讯网——每日最新资讯28at.com

ISOLATION_REPEATABLE_READhNr28资讯网——每日最新资讯28at.com

可重复读:目标是克服读写提交中出现的不可重复读的现象,因为在读写提交的时候,可能出现一些值的变化,影响当前事务的执行
hNr28资讯网——每日最新资讯28at.com

ISOLATION_SERIALIZABLEhNr28资讯网——每日最新资讯28at.com

串行化,数据库最高的隔离级别,它会要求所有的 SQL 都会按照顺序执行,这样就可以克服上述隔离级别出现的各种问题,所以它能够完全保证数据的一致性
hNr28资讯网——每日最新资讯28at.com

超时时间 ( @Transactional ( timeout = 30 ) ): 定义一个事务执行过程多久算超时,以便超时后回滚。可以防止长期运行的事务占用资源.对应注解中的属性 timeout (注意点:这个超时时间在数据库事务超时的范畴内的)hNr28资讯网——每日最新资讯28at.com

是否只读 ( @Transactional ( readOnly = true ) ):表示这个事务只读取数据但不更新数据hNr28资讯网——每日最新资讯28at.com

回滚机制( @Transactional ( rollbackFor = Exception.class ):定义遇到异常时回滚策略hNr28资讯网——每日最新资讯28at.com

传播机制( @Transactional ( propagation = Propagation.REQUIRED ): 对事务的传播特性进行定义,共有 7 种类型 (一个事务内调用另外一个事务)hNr28资讯网——每日最新资讯28at.com

事务行为
hNr28资讯网——每日最新资讯28at.com

说明
hNr28资讯网——每日最新资讯28at.com

PROPAGATION_REQUIRED
hNr28资讯网——每日最新资讯28at.com

如果当前上下文中存在事务,那么加入该事务,如果不存在事务,创建一个事务,这是默认的传播属性值
hNr28资讯网——每日最新资讯28at.com

PROPAGATION_SUPPORTS
hNr28资讯网——每日最新资讯28at.com

如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,则使用非事务的方式执行
hNr28资讯网——每日最新资讯28at.com

PROPAGATION_MANDATORY
hNr28资讯网——每日最新资讯28at.com

支持当前事务,假设当前没有事务,就抛出异常
hNr28资讯网——每日最新资讯28at.com

PROPAGATION_REQUIRES_NEW
hNr28资讯网——每日最新资讯28at.com

每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行
hNr28资讯网——每日最新资讯28at.com

PROPAGATION_NOT_SUPPORTED
hNr28资讯网——每日最新资讯28at.com

如果当前上下文中存在事务,则挂起当前事务,然后新的方法在没有事务的环境中执行
hNr28资讯网——每日最新资讯28at.com

PROPAGATION_NEVER
hNr28资讯网——每日最新资讯28at.com

如果当前上下文中存在事务,则抛出异常,否则在无事务环境上执行代码
hNr28资讯网——每日最新资讯28at.com

PROPAGATION_NESTED
hNr28资讯网——每日最新资讯28at.com

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。
hNr28资讯网——每日最新资讯28at.com

三、常见的 @Transactional 注解 事务没生效的场景

1、访问权限问题 (只有 public 方法会生效)

示例代码:hNr28资讯网——每日最新资讯28at.com

@Servicepublic class UserService {  @Transactional  private void add(UserModel userModel) {    saveData(userModel);    updateData(userModel);  }}

原因:Spring 要求被代理方法必须得是 public 的hNr28资讯网——每日最新资讯28at.com

图片hNr28资讯网——每日最新资讯28at.com

也就是说,如果我们自定义的事务方法(即目标方法),它的访问权限不是 public,而是 private、 default 或 protected 的话, Spring 则不会提供事务功能hNr28资讯网——每日最新资讯28at.com

2、方法用 final 修饰,不会生效

示例代码:hNr28资讯网——每日最新资讯28at.com

@Servicepublic class UserService {  @Transactional  public final void add(UserModel userModel){    saveData(userModel);    updateData(userModel);  }}

原因:hNr28资讯网——每日最新资讯28at.com

Spring 事务底层使用了 AOP,也就是通过 JDK 动态代理或者 CGLIB,帮我们生成了代理类,在代理类中实现的事务功能。但如果某个方法用 final 修饰了,那么在它的代理类中,就无法重写该方法,而添加事务功能。hNr28资讯网——每日最新资讯28at.com

注意:如果某个方法是 static 修饰的,同样无法通过动态代理,变成事务方法。hNr28资讯网——每日最新资讯28at.com

3、同一个方法内直接调用,会造成事务失效

示例代码:hNr28资讯网——每日最新资讯28at.com

@Servicepublic class UserService {  @Autowired  private UserMapper userMapper;    public void add(UserModel userModel) {    userMapper.insertUser(userModel);    updateStatus(userModel);  }  @Transactional  public void updateStatus(UserModel userModel) {    doSameThing();  }}

原因:hNr28资讯网——每日最新资讯28at.com

我们看到在事务方法 add 中,直接调用事务方法 updateStatus。从前面介绍的内容可以知道, updateStatus 方法拥有事务的能力是因为 Spring AOP 生成代理了对象,但是这种方法直接调用了 this 对象的方法,并不会从 IOC 拿到加上 AOP 事务相关方法的动态代理对象 所以 updateStatus 方法不会生成事务hNr28资讯网——每日最新资讯28at.com

4、(类本身) 未被 Spring 管理

示例代码:hNr28资讯网——每日最新资讯28at.com

//@Servicepublic class UserService {  @Transactional  public void add(UserModel userModel) {    saveData(userModel);    updateData(userModel);  }    }

原因:hNr28资讯网——每日最新资讯28at.com

使用 Spring 事务的前提是:对象要被 Spring IOC 管理,需要创建 bean 实例hNr28资讯网——每日最新资讯28at.com

5、多线程调用

示例代码:hNr28资讯网——每日最新资讯28at.com

@Servicepublic class UserService {  @Autowired  private UserMapper userMapper;  @Autowired  private RoleService roleService;  @Transactional  public void add(UserModel userModel) throws Exception {    userMapper.insertUser(userModel);      new Thread(() -> {        roleService.doOtherThing();      }).start();  }}@Servicepublic class RoleService {  @Transactional  public void doOtherThing() {  }}

原因:同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务。hNr28资讯网——每日最新资讯28at.com

6、错误的传播特性

示例代码:hNr28资讯网——每日最新资讯28at.com

@Servicepublic class UserService {  @Autowired  private UserMapper userMapper;  @Autowired  private RoleService roleService;    @Transactional(propagation = Propagation.REQUIRED)  public void add(UserModel userModel) throws Exception {    userMapper.insertUser(userModel);      new Thread(() -> {        roleService.doOtherThing();      }).start();  }}@Servicepublic class RoleService {  @Transactional(propagation = Propagation.NEVER)  public void doOtherThing() {  }}

原因:RoleService 中 doOtherThing() 方法上设置的事物传播类型为 Propagation.NEVER,即存在事务就抛出异常hNr28资讯网——每日最新资讯28at.com

7、自己吞了异常

示例代码:hNr28资讯网——每日最新资讯28at.com

@Slf4j@Servicepublic class UserService {  @Transactional  public void add(UserModel userModel) {    try {      saveData(userModel);      updateData(userModel);    } catch (Exception e) {      log.error(e.getMessage(), e);    }  }}

原因:如果想要 Spring 事务能够正常回滚,必须抛出它能够处理的异常。如果没有抛异常,则 Spring 认为程序是正常的。hNr28资讯网——每日最新资讯28at.com

8、抛出的异常,事务管理器处理不了,则不会回滚

示例代码:hNr28资讯网——每日最新资讯28at.com

@Slf4j@Servicepublic class UserService {  @Transactional  public void add(UserModel userModel) throws Exception {    saveData(userModel);    updateData(userModel);  }}

原因:@Transactional 默认的异常类型是 RuntimeException,如果出现非 RuntimeException,则 Spring 事务处理不了对应的异常,认为程序是正常的,则不会回滚事务,此时我们可以指定异常类型如 @Transactional(rollbackFor = Exception.class)hNr28资讯网——每日最新资讯28at.com

9、数据库引擎不支持事务

比如 Mysql 中的 MyISAM 引擎是不支持事务操作的, InnoDB 才是支持事务的引擎hNr28资讯网——每日最新资讯28at.com

四、总结:

本文通过对 @Transactional 注解相关介绍,列举出可能会出现事务失效的场景。发生最多就是自身调用、异常被吃、异常抛出类型不匹配这三个。由于平时业务繁重,有时候会忽视 @Transactional 注解使用规范,导致事务没有生效或者没有正常回滚,造成较大的数据异常。希望可以帮助大家日常使用 @Transactional 时避坑。hNr28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-11732-0.html@Transactional注解使用以及事务失效的场景

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 玩转SpringBoot—自动装配解决Bean的复杂配置

下一篇: React中的依赖注入,看这一篇就够了!

标签:
  • 热门焦点
  • 直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    旗舰机基本上使用的都是双曲面屏幕,这就让很多喜欢直屏的爱好者在苦等一款直屏旗舰,这次,你们等到了。据博主数码闲聊站带来的最新爆料称,Redmi下代旗舰K70 Pro和iQOO 12两款手
  • Rust中的高吞吐量流处理

    Rust中的高吞吐量流处理

    作者 | Noz编译 | 王瑞平本篇文章主要介绍了Rust中流处理的概念、方法和优化。作者不仅介绍了流处理的基本概念以及Rust中常用的流处理库,还使用这些库实现了一个流处理程序
  • 2023 年的 Node.js 生态系统

    2023 年的 Node.js 生态系统

    随着技术的不断演进和创新,Node.js 在 2023 年达到了一个新的高度。Node.js 拥有一个庞大的生态系统,可以帮助开发人员更快地实现复杂的应用。本文就来看看 Node.js 最新的生
  • 分享六款相见恨晚的PPT模版网站, 祝你做出精美的PPT!

    分享六款相见恨晚的PPT模版网站, 祝你做出精美的PPT!

    1、OfficePLUSOfficePLUS网站旨在为全球Office用户提供丰富的高品质原创PPT模板、实用文档、数据图表及个性化定制服务。优点:OfficePLUS是微软官方网站,囊括PPT模板、Word模
  • 十个简单但很有用的Python装饰器

    十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • 之家push系统迭代之路

    之家push系统迭代之路

    前言在这个信息爆炸的互联网时代,能够及时准确获取信息是当今社会要解决的关键问题之一。随着之家用户体量和内容规模的不断增大,传统的靠"主动拉"获取信息的方式已不能满足用
  • 小红书1周涨粉49W+,我总结了小白可以用的N条涨粉笔记

    小红书1周涨粉49W+,我总结了小白可以用的N条涨粉笔记

    作者:黄河懂运营一条性教育视频,被54万人“珍藏”是什么体验?最近,情感博主@公主是用鲜花做的,火了!仅仅凭借一条视频,光小红书就有超过128万人,为她疯狂点赞!更疯狂的是,这
  • 中国家电海外掘金正当时|出海专题

    中国家电海外掘金正当时|出海专题

    作者|吴南南编辑|胡展嘉运营|陈佳慧出品|零态LT(ID:LingTai_LT)2023年,出海市场战况空前,中国创业者在海外纷纷摩拳擦掌,以期能够把中国的商业模式、创业理念、战略打法输出海外,他们依
  • “买真退假” 这种“羊毛”不能薅

    “买真退假” 这种“羊毛”不能薅

    □ 法治日报 记者 王春   □ 本报通讯员 胡佳丽  2020年初,还在上大学的小东加入了一个大学生兼职QQ群。群主“七王”在群里介绍一些刷单赚
Top
Baidu
map