在Web 开发中,Spring 框架已经成为了众多开发者的首选。Spring 的声明式事务管理是其中最重要的特性之一,它可以帮助我们简化业务逻辑的复杂度,并且确保在出现异常情况时数据的一致性。
事务失效情况很常见,但我们只要注意,就可以避免事情发生!在本文中,我将详细地介绍Spring 声明式事务的源码实现和事务失效常见的五种情况,并给出有效的解决方案。
(资料图片仅供参考)
其实我们常说的事务失效是声明式事务(@Transactional)的失效,本文也是从声明式事务来进行演示的!
通过本文的学习,你将掌握如何正确地使用 Spring 的事务管理,减少生产事故。
「一定要保持数据一致性」。
二、@Transactional注解参数解读我们拿出几个经常使用的参数来简单介绍一下:
propagation:指定事务的传播行为。其取值包括 REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER 和 NESTED 等。默认为REQUIRED。 其中,REQUIRED 表示如果当前已经存在一个事务,则加入该事务,否则新建一个事务;而 REQUIRES_NEW 表示新建一个独立的事务,如果当前已经存在事务,则挂起当前事务。后面就不一一说了,大家可以自行百度哈!isolation:指定事务的隔离级别。其取值包括 DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE 等。默认为 DEFAULT。 其中,DEFAULT 表示采用数据库的默认隔离级别.timeout:指定事务的超时时间,单位为秒。默认为 -1,表示不设置超时时间。如果在规定时间内事务还未完成,则抛出 TransactionTimedOutException 异常。readOnly:指定事务是否只读,即是否允许修改数据。默认为 false,表示可以进行数据修改操作。如果将其设置为 true,则表示该事务仅能进行数据查询操作,不能进行数据修改操作,这样可以提高并发性能。rollbackFor:指定哪些异常需要回滚事务。其取值为一个 Class 数组,其中每个元素表示一个异常类型。默认为空,表示只有抛出 RuntimeException 或 Error 类型的异常时才回滚事务。noRollbackFor:指定哪些异常不需要回滚事务。其取值为一个 Class 数组,其中每个元素表示一个异常类型。默认为空,表示抛出任何异常都回滚事务。三、声明式事务源码实现声明式事务实现类为:TransactionInterceptor,下面我们来一起看看这个类!
源码版本为Springboot2.7.1。
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable{}
TransactionInterceptor UML图:
声明式事务主要是通过AOP实现,主要包括以下几个节点:
启动时扫描@Transactional注解:在启动时,Spring Boot会扫描所有使用了@Transactional注解的方法,并将其封装成TransactionAnnotationParser对象。AOP 来实现事务管理的核心类依然是TransactionInterceptor。TransactionInterceptor 是一个拦截器,用于拦截使用了 @Transactional 注解的方法将TransactionInterceptor织入到目标方法中:在AOP编程中,使用AspectJ编写切面类,通过@Around注解将TransactionInterceptor织入到目标方法中。在目标方法执行前创建事务:在目标方法执行前,TransactionInterceptor会调用PlatformTransactionManager创建一个新的事务,并将其纳入到当前线程的事务上下文中。执行目标方法:在目标方法执行时,如果发生异常,则将事务状态标记为ROLLBACK_ONLY;否则,将事务状态标记为COMMIT。提交或回滚事务:在目标方法执行完成后,TransactionInterceptor会根据事务状态(COMMIT或ROLLBACK_ONLY)来决定是否提交或回滚事务。源码:
@Override@Nullablepublic Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport"s invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() { @Override @Nullable public Object proceedWithInvocation() throws Throwable { return invocation.proceed(); } @Override public Object getTarget() { return invocation.getThis(); } @Override public Object[] getArguments() { return invocation.getArguments(); } });}
下面是核心处理方法,把不太重要的代码忽略了,留下每一步的节点。
@Nullableprotected Object invokeWithinTransaction(Method method, @Nullable Class> targetClass, final InvocationCallback invocation) throws Throwable { // 获取事务属性 final TransactionManager tm = determineTransactionManager(txAttr); // 准备事务 TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status); // 执行目标方法 Object retVal = invocation.proceedWithInvocation(); // 回滚事务 completeTransactionAfterThrowing(txInfo, ex); // 提交事务 commitTransactionAfterReturning(txInfo);}
四、五种失效和解决方案下面我们从几个情况来给大家展示失效场景并给出解决方案。
1、类没有被 Spring 管理public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override @Transactional(rollbackFor = Exception.class) public void addUser(User user) { userDao.addUser(user); }}
如上代码所示,UserServiceImpl 类没有被声明为 Spring Bean,因此其中的 addUser() 方法无法受到 Spring 事务管理的保护。 我们使用Spring,要把类交给Spring进行管理,不然是无法生效!
「解决方案:」交给spring进行管理bean,在类上添加:@Service!
2、方法不是public修饰@Servicepublic class UserService { @Autowired private UserDao userDao; @Transactional(rollbackFor = Exception.class) protected void addUser(User user) { userDao.addUser(user); }}
我们上面说了声明式事务是基于AOP实现的,AOP是通过代理模式实现的,即为目标对象生成一个代理对象,当调用代理对象的方法时,会自动添加事务的控制代码。 在这种情况下,如果事务注释所在的方法不是public的,则无法生成代理对象,因此事务代码将无法添加到方法执行前后,导致事务失效。
其实这种情况还是不经常这么使用,我们基本都是使用接口和实现大部分都是public修饰的!
「解决方案:」使用public来修饰方法。
3、异常被捕获并处理了@Servicepublic class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override @Transactional(rollbackFor = Exception.class) public void addUser(User user) { try { userDao.addUser(user); } catch (Exception e) { // 处理异常,但没有抛出或重新抛出异常 log.error("add user error", e); } }}
如上代码所示,如果 userDao.addUser() 方法抛出异常,但是在 UserServiceImpl.addUser() 中被捕获并处理了,事务检测不到有异常抛出,那么事务不会回滚。
「解决方案:」catch 处理完成后,在重新把异常在抛出去:throw e。
4、同一个类中,方法内部调用@Servicepublic class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public void addUser(User user) { doAddUser(user); } @Transactional(rollbackFor = Exception.class) public void doAddUser(User user) { userDao.addUser(user); }}
Spring使用代理来实现事务控制,但是这种方法直接调用了this对象的方法,则无法通过代理来拦截该方法调用,从而使得事务失效。
「解决方案:」推荐使用有两种:
使用ApplicationContext来获取当前bean对象来调用doAddUser方法。在addUser方法加上@Transactional(rollbackFor = Exception.class)。网上还有一些使用AopContext.currentProxy()拿到代理对象的、自己注入自己的、抽到单独的bean里的 这里小编不是很推荐!
方法一完整展示:
如果觉得Service里注入ApplicationContext 不优雅,可以抽到单独的工具bean里!
@Servicepublic class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Autowired private ApplicationContext applicationContext; @Override public void addUser(User user) { UserServiceImpl userService = applicationContext.getBean(UserServiceImpl.class); userService.doAddUser(user); } @Transactional(rollbackFor = Exception.class) public void doAddUser(User user) { userDao.addUser(user); }}
5、MySQL存储引警不支持事务MyISAM存储引擎是 MySQL 的一种存储引擎,它是 MySQL5.1 版本之前的默认存储引擎,它是不支持事务的。从 MySQL 5.5 版本开始,InnoDB 成为了 MySQL 的默认存储引擎。我们想使用也可以切换到MyISAM引擎。
「解决方案:」把mysql换到5.5以上使用InnoDB存储引擎。
「补充使用MyISAM 方式:」表从 InnoDB 引擎转换为 MyISAM 引擎:使用 ALTER TABLE 命令来更改表的引擎类型。ALTER TABLE table_name ENGINE = MyISAM;
默认的存储引擎设置为 MyISAM, 可以在 MySQL 配置文件中设置 default-storage-engine 参数。default-storage-engine=MyISAM
创建表时指定MyISAM 引擎 要将表的引擎类型设置为 MyISAM,请在 CREATE TABLE 语句中包含 ENGINE = MyISAM 子句CREATE TABLE table_name ( column1 datatype, column2 datatype, ...) ENGINE = MyISAM;
五、总结本文总结了Spring 声明式事务的源码实现、五种常见的事务失效情况,并提供了相应的解决方案。
当然还有很多情况:被final修饰、多线程调用、传播行为使用不当、抛的异常不对应等等
理解 Spring 事务机制的,深入了解 Spring 事务的内部原理。同时,在使用声明式事务的过程中,我们也可以针对自己的业务场景进行定制化的配置,比如指定特定的事务传播机制、设置超时时间等,这些都有助于更好地应对复杂的业务场景和代码需求。这样才能真正地提高系统的可维护性、可扩展性和稳定性。
标签:
上一篇 : 开年不到5个月 基金经理离职人数已过百_环球关注
下一篇 : 最后一页
“我们这一批人,都是因乡愁而归国。为打造精品民宿,吴勇强融入了“稻鱼文化”“华侨文化”“乡愁文化...
05-26 13:09:05
每经AI快讯,有投资者在投资者互动平台提问:公司600万募投产能项目进展到哪一步了?预计什么时候验收?康
05-26 12:18:45
为统筹推进教育教学与疫情防控工作,多地近日发布教学安排,有序恢复中小学线下教学。
05-26 11:15:19
5月25日,麦捷科技(300319)融资买入303 58万元,融资偿还527 07万元,融资净卖出223 5万元,融资余额1 98亿元。
05-26 10:55:35
工作、学习、社交、运动……无论干啥没有不需要脑力的。每天大脑都要高速运转来处理各种事情,有没有什...
05-26 10:07:25
1、首重1KG20元,续重1KG10元(人民币)是按照重量计算的。2、大约2-3个日到。本文就为大家分享到这里,
05-26 09:02:14
远东股份合同范本第1篇甲方:乙方:现甲、乙双方经过友好协商,本着平等互利、友好合作的意愿达成本协议书
05-26 08:35:36
1、概况安乡偎麻雀是安乡县民间最为盛行的一种纸牌游戏,现在基本上已流传到了整个常德市,成为湘北人最喜
05-26 07:36:10
1、性压抑,也叫性饥饿,是指人对自身性欲望的制约与控制。2、表现为在一段时期内控制发生性行为的频率,将
05-26 06:40:58
香料:干辣椒15克、八角8克、花椒8克、白芷5克、白蔻4克、香叶2克。配料:海鲜酱30克、黄豆酱30克、花生酱1
05-26 05:57:12
1、要做什么生意,做什么产品,一定要有需求才行。2、一定要有特色,你可以看看这个到底怎么样,说到特色。
05-26 04:40:12
相信目前很多小伙伴对于阿斯塔兽都比较感兴趣,那么小搜今天在网上也是收集了一些与阿斯塔兽相关的信息来分
05-26 03:45:40
1、是孟尧本人。2、我有看过删减部分的视频。3、确实很诱人。本文分享完毕,希望对大家有所帮助。
05-26 03:04:10
今年1月份至4月份,我国实际使用外资4994 6亿元人民币,吸引外资延续了稳健增长的态势。我国吸引外资数量整
05-26 02:39:11
教育部今天(25日)发出预防学生溺水工作预警。近期,全国各地气温迅速回升,汛期即将来临,溺水事故进入高
05-26 01:06:25
厦门海事法院平潭综合实验区巡回审判点揭牌5月16日,厦门海事法院、平潭综合实验区人民法院“深化交流协...
05-26 00:36:14
金融界APP2022年9月15日讯,盈方微(000670)报收8 82元,跌幅-10 00%,成交量10915 02万
05-25 23:36:21
1、解释:风和雪同时袭来。2、出自:元·程文海《浣溪沙·题湘水行吟》词:“风雪交加冻不醒,抱琴谁共...
05-25 23:33:54
中新网湖南新闻5月25日电5月25日,由中国牙病防治基金会主办、中华预防医学会健康传播分会学术支持,赫力昂
05-25 21:53:05
1、陕西工商技术学院学费:广告设计与制作、广播影视节目制作、舞台艺术设计与制作专业7500元 学年;其他专
05-25 21:08:43
1、tuó如名人:柁嘉熹tuójiāxī。本文分享完毕,希望对大家有所帮助。
05-25 20:09:29
提到杨童舒,估计很多人都不知道她是谁,名字比较陌生,但是只要一提到《至尊红颜》里的徐盈盈,大家就会恍
05-25 19:29:34
《美国留学开支大概多少钱》由留学费用网发布,主要内容:美国留学一年的费用在很多人看来是相当昂贵的。但不
05-25 18:11:34
想必现在有很多小伙伴对于360查杀C: Windows system32 dx000sys木马程序(Trojan Ge
05-25 17:51:32
全年减少11万吨玻璃用量,相当于减少2200万立方天然气使用;节约标煤7249吨,相当于减少5 3万吨二氧化碳排
05-25 17:27:26
中新网5月25日电据国家能源局25日消息,截至今年4月底,我国风电装机3 8亿千瓦,光伏发电装机4 4亿千瓦,风
05-25 16:53:19
本文来源:时代财经作者:张榕自100多年前世界上第一例阿尔茨海默病(以下简称“AD”)患者被发现以来,科...
05-25 16:15:55
富源县气象台2023年5月25日11时00分继续发布大风蓝色预警信号:预计未来24小时我县仍将出现大风天气,平均
05-25 15:20:01
近日,网传天津一男子当街持剪刀伤人。视频显示,一男子握着剪刀挟持一女子,围观路人突然用铁锹将其拍蒙后
05-25 14:47:31
湖人总经理佩林卡也是站出来表示,当球员的职业生涯达到一个拐点的时候,他们会做出不一样的选择。“勒...
05-25 14:15:31
红网时刻新闻5月25日讯(通讯员陈积粮)5月24日,株洲市市场监管局对特殊食品大中型销售企业和连锁销售企业
05-25 12:47:31
六福珠宝黄金价格今天多少一克,六福珠宝今日金价(2023年05月25日)
05-25 11:55:04
格隆汇5月25日丨慈文传媒跳空低开,现跌超5%报7 82元,股价刷新调整低价,总市值37亿元。公司昨晚公告,持
05-25 11:25:16
充电桩板块早盘强势,金冠股份、汉马科技涨停,蓝海华腾、惠程科技大涨超8%,绿能慧充、通合科技涨超5%。消
05-25 10:49:04
中新网5月24日电据韩联社报道,韩国自研火箭“世界号”原计划于当地时间24日下午发射升空,但因出现技术...
05-25 10:06:09
这套重载铁路运维系统多智能?故障精准定位、零部件批量更换
05-25 09:19:48
北京时间5月25日,美股三大指数集体收跌,道指跌0 77%,标普500指数跌0 73%,纳指跌0 61%。在收盘铃声敲响
05-25 08:23:32
作者|李文博编辑|周到2011年,当国内汽车市场还是一片尚未开垦的蛮荒之地时,朴实的中国人在买车时,总会
05-25 07:31:20
来为大家解答以上的问题。歌吟是什么意思百度网盘,歌吟是什么意思这个很多人还不知道,现在让我们一起来看
05-25 06:30:40
1、波纹补偿器属于一种补偿元件。2、利用其工作主体波纹管的有效伸缩变形,以吸收管线、导管、容器等由热胀
05-25 05:28:10
中新网北京5月24日电中国国务委员兼外长秦刚23日在北京同荷兰副首相兼外交大臣胡克斯特拉会谈后向记者介绍
05-25 04:19:43
江苏省高龄津贴发放标准:年龄划分、补贴金额一次讲清楚!根据要求,江苏省建立高龄津贴补助方案:向有江苏
05-25 04:34:49
1、现在山鸡苗批发价4 5一只,买苗一定要到正规厂家,如业界种苗养殖场。2、小房珍禽,提供种苗,养殖技术
05-25 03:17:52
1、学校社团很多啊。2、机自专业很好啊。3、男生多女生少。4、男女比例10:1还夸张。5、机自跟我是一个学院
05-25 01:28:47
劳动仲裁要的证明材料有劳动仲裁申请书、用人单位的工商登记资料、劳动者的身份证及复印件,能证明劳动者与
05-25 01:24:32
5月24日,由司徒兆敦担任总顾问,藏族导演乔美执导的电影《乔治娅》宣布定档6月3日,并首度曝光定档海报。本片
05-25 00:43:25
互联网新闻信息服务许可证编号611202100115月24日,延安市退役军人事务局局长、市双拥办主任张军一行来我县
05-24 23:15:51
我们的照片上如果有马赛克,那我们怎么把马赛克去除呢?这是我们要弄懂的事情,那就学下:怎么去除马赛克?
05-24 22:58:14
今天来聊聊关于辣木籽的功效与作用及禁忌哺乳期可以吃吗,辣木籽的功效与作用及禁忌的文章,现在就为大家来
05-24 21:11:53
1、抖音孙冰法未公布其年龄。2、孙冰法的年龄看样子是个95后,年龄大概就是20到25之间。3、孙冰法的短视频
05-24 20:57:21
“我们这一批人,都是因乡愁而归国。为打造精品民宿,吴勇强融入了“稻鱼文化”“华侨文化”“乡愁文化...
2023-05-26
每经AI快讯,有投资者在投资者互动平台提问:公司600万募投产能项目进展到哪一步了?预计什么时候验收?康
2023-05-26
为统筹推进教育教学与疫情防控工作,多地近日发布教学安排,有序恢复中小学线下教学。
2023-05-26
5月25日,麦捷科技(300319)融资买入303 58万元,融资偿还527 07万元,融资净卖出223 5万元,融资余额1 98亿元。
2023-05-26
工作、学习、社交、运动……无论干啥没有不需要脑力的。每天大脑都要高速运转来处理各种事情,有没有什...
2023-05-26
Copyright © 2015-2022 热讯纤维网版权所有 备案号:豫ICP备20005723号-6 联系邮箱:29 59 11 57 8@qq.com