为什么有的公司会禁用spring声明式事务

news2024/12/24 2:38:18

在之前我一直偏向于使用声明式事务,我一直觉得声明式事务比较好用。相比于编程式事务,使用声明式事务时只需要加上一个注解,spring就能够帮助我们完成所有的事务控制。反观编程式事务却需要我们自己去控制事务的提交和回滚,这种代码入侵的事务编程看起来也不是那么优雅。

但是最近在和朋友聊天时发现他们公司缺禁止使用声明式事务?这是为什么呢?

其实原因也很简单,虽然声明式事务方便好用,但是有一个致命的缺陷,就是一旦使用不当,很容易造成事务失效。下面这个博客里面我罗列了部分失效的情况,如果不了解的可以看一下。

spring 事务传播行为以及失效原因_极速小乌龟的博客-CSDN博客今天在查看以前写的代码时,看到了事务的使用,感觉自己对这一块并不是特别清晰,所以就系统的学习了一下。在学习过程中发现很多地方自己以前理解的还是有点不对,所以记录一下学习笔记,希望帮助到大家。备注:因为除了PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED,其他的都不是特别难以理解,所以我这里就只对这两个做了一下代码实例。当事务方法被另外一个事务方法调用时,必须指定事务应该如何传播,例如,方法可能继续在当前事务中执行,也可以开启一个新的事务,在自己的事务中执行。声明式事务https://blog.csdn.net/qq_35771266/article/details/128222174说实话这个对我触动也有点大,之前一直以为编程式事务是一个过时的东西,操作不方便也不好用。但是现在我知道了编程式事务最起码能避免事务的失效。不过就个人而言,我觉得声明式事务还是非常好用的,我们在开发时如果说比较简单的事务,或者能够肯定生命式事务不会出问题的情况下,我觉得使用声明式事务就可以了。要是非常重要的逻辑而且逻辑比较复杂不能够清晰判定事务不会出问题时,我觉得保险起见可以使用编程式事务。

一、编程式事务的使用

编程式事务的使用也很简单,就是代码比较多,写着有点小不爽。下面我来贴一下代码,各位看一下:

 @Autowired
    private PlatformTransactionManager transactionManager;


    /**
     * description: insertUser  插入用户信息<br>
     * @version: 1.0
     * @date: 2022/12/28 0028 下午 2:41
     * @author: William
     * @param user   用户信息
     * @return com.example.springbootdemo.common.response.Result
     */
    @ApiOperation(value = "插入用户信息")
    @PostMapping
    public Result insertUser(@RequestBody User user){
        //参数校验。。。
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        boolean flag = false;
        try {
            // 数据库操作
            flag = userService.save(user);
            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            transactionManager.rollback(transactionStatus);
            throw new MyException(ErrorCodeEnum.OPERATION_FAILED);
        }
        return flag?Result.ok():Result.error(ErrorCodeEnum.OPERATION_FAILED);
    }

 其实这么多代码就做了一步数据插入的操作,我们如果使用声明式事务,代码是什么样的呢?

/**
     * description: insertUser  插入用户信息<br>
     * @version: 1.0
     * @date: 2022/12/28 0028 下午 2:41
     * @author: William
     * @param user   用户信息
     * @return com.example.springbootdemo.common.response.Result
     */
    @ApiOperation(value = "插入用户信息")
    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public Result insertUser(@RequestBody User user){
        //参数校验。。。。
        boolean flag = userService.save(user);
        return flag?Result.ok():Result.error(ErrorCodeEnum.OPERATION_FAILED);
    }

真是没有对比就没有伤害。如果说在开发中每次用到这样写一遍,讲真内心是崩溃的。所以我们还需要对他进行一次升级。

二、升级版编程式事务

其实稍微留心我们就能发现,事务的开启,提交和回滚是固定的,唯一发生变化的也就是中间的业务逻辑。所以我们可以把公共的部分给它抽取出来就好了。具体实现代码如下:

package com.example.springbootdemo.common.utils;

import com.example.springbootdemo.common.enums.ErrorCodeEnum;
import com.example.springbootdemo.common.exception.MyException;
import com.example.springbootdemo.common.response.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.function.Function;

/**
 * @description: TransactionUtils <br>
 * @date: 2022/12/28 0028 下午 3:16 <br>
 * @author: William <br>
 * @version: 1.0 <br>
 */
@Component
public class TransactionUtils {

    @Autowired
    private PlatformTransactionManager transactionManager;

    public <R,T> R queryItem(T t,Function<T,R> dbCallBack){
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        R r;
        try {
            // 数据库操作
            r = dbCallBack.apply(t);
            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            transactionManager.rollback(transactionStatus);
            throw new MyException(ErrorCodeEnum.OPERATION_FAILED);
        }
        return r;
    }
}

这样的话我们在来看看刚刚的代码:

    @Autowired
    private TransactionUtils transactionUtils;

    /**
     * description: insertUser  插入用户信息<br>
     * @version: 1.0
     * @date: 2022/12/28 0028 下午 2:41
     * @author: William
     * @param user   用户信息
     * @return com.example.springbootdemo.common.response.Result
     */
    @ApiOperation(value = "插入用户信息")
    @PostMapping
    public Result insertUser(@RequestBody User user){
        //参数校验。。。。
        boolean flag = transactionUtils.queryItem(user, u -> userService.save(user));
        return flag?Result.ok():Result.error(ErrorCodeEnum.OPERATION_FAILED);
    }

怎么样是不是舒服多了?看着也优雅了很多,这样我们在开发中相比于声明式事务也就多导入一个类,然后调用一次方法就好了。

不过上面这个版本也只是一个思路版本,如果小伙伴有需要使用的,我觉得可以按照这种思路自己去个性化定制就好了。

如果文章对你有所帮助的话,麻烦点赞关注呦,谢谢啦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124317.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaSE】Clonable?关于深拷贝与浅拷贝那些事儿咱们一次聊明白

&#x1f481; 个人主页&#xff1a;黄小黄的博客主页 ❤️ 支持我&#xff1a;&#x1f44d; 点赞 &#x1f337; 收藏 &#x1f918;关注 &#x1f38f; 格言&#xff1a;All miracles start from sometime somewhere, make it right now. 本文来自专栏&#xff1a;JavaSE从入…

新年新气象,100行 Python 代码制作动态鞭炮

放鞭炮贺新春&#xff0c;在我国有两千多年历史。关于鞭炮的起源&#xff0c;有个有趣的传说。 西方山中有焉&#xff0c;长尺余&#xff0c;一足&#xff0c;性不畏人。犯之令人寒热&#xff0c;名曰年惊惮&#xff0c;后人遂象其形&#xff0c;以火药为之。——《神异经》 当…

IU8689 单声道145W/75W立体声D类音频功放IC产品介绍

概要 IU8689E是-款单声道可输出145W,立体声2*75W D类音频功率放大器&#xff0c;这款器件在顶层设计了散热焊盘&#xff0c;焊盘上连接散热器后在供电电压24V的情况下&#xff0c;最大可以输出2x75W的连续功率&#xff1b;通过主从模式的设置可以让IU8689E实现无限级联&#x…

C# 线程的基本使用

一 多线程的概念 1 进程Process 2 线程Thread ① 线程中的指令&#xff1a;一个方法&#xff08;委托&#xff09; ② 线程中的数据&#xff1a;相关的对象&#xff1b; 3 System.Threading.Thread属性 4 System.Threading.Thread方法 5 线程的创建 1&#xff09; Thread类…

初识Spring

目录 一&#xff1a; 为什么要学习&#xff1f; 二&#xff1a; 概述 三&#xff1a;Spring发展史 一&#xff1a; 为什么要学习&#xff1f; 可以最大程度地简化项目的开发大量公司在使用顶级的源码设计:spring框架源码设计非常优秀&#xff0c;在java开源项目中可以说是顶…

1.8T数据离奇消失之谜

编者按 数字化浪潮蓬勃兴起&#xff0c;企业面临的安全挑战亦日益严峻。 腾讯安全近期将复盘2022年典型的攻击事件&#xff0c;帮助企业深入了解攻击手法和应对措施&#xff0c;完善自身安全防御体系。 本篇是第六期&#xff0c;讲述了某企业NAS系统数据被删除&#xff0c;始…

SpringBoot 配合126邮箱实现邮件发送功能

126邮箱邮件发送授权码申请pom依赖邮件配置代码编写Bean与配置自动装载原始手工方式发送邮件发送纯文本的邮件发送包含HTML标签的邮件发送包含附件的邮件发送包含静态资源的文件测试SpringBoot 提供了系统级别邮箱服务&#xff0c;只需要导入一个邮箱启动器然后进行配置就可以使…

LabVIEW如何减少下一代测试系统中的硬件过时6

LabVIEW如何减少下一代测试系统中的硬件过时6 HAL Benefits When addressing obsolescence, HALs yield the benefits of lowermigration costs, faster migration time, higher code reuse, and easiermaintainability. Lower Migration Costs The act of designing a use…

如何pdf合并成一个?推荐3种方法

在企业处理多份合同文件或者财务报销时&#xff0c;经常会处理大量的PDF文件。因此为了更高效率办公&#xff0c;我们经常需要将多个pdf合并成一个。如何pdf合并成一个呢&#xff1f;给大家推荐3个方法。 1、Smallpdf工具 如何pdf合并成一个&#xff1f;推荐大家可以使用Small…

一篇canvas带你画出整个特效世界

目录 一&#xff0c;canvas是啥&#xff1f; 1.初识canvas 2.路径绘制 3.拆分画法 4.清除画布 5.绘制圆形笑脸 6.贝塞尔曲线 ①二次贝塞尔曲线 ②三次贝塞尔曲线 一&#xff0c;canvas是啥&#xff1f; Canvas是HTML5中新出的一个元素&#xff0c;我们可以在上面绘制…

为什么redis中提供hash数据类型?

目录 1.什么是哈希表&#xff1f;缺点是什么&#xff1f; 2.Redis的数据类型&#xff08;type、encoding&#xff09; 3.比较常用命令、使用场景、实现方式 1.什么是哈希表&#xff1f;缺点是什么&#xff1f; 把关键字key映射到表中记录的地址。映射关系是散列函数&#x…

图表控件LightningChart.NET 入门教程(六):许可证管理介绍(上)

LightningChart.NET SDK 是一款高性能数据可视化插件工具&#xff0c;由数据可视化软件组件和工具类组成&#xff0c;可支持基于 Windows 的用户界面框架&#xff08;Windows Presentation Foundation&#xff09;、Windows 通用应用平台&#xff08;Universal Windows Platfor…

初学Java web(十)Filter 和 Listener

Filter和Listener 一.Filter 概念&#xff1a;Filter表示过滤器&#xff0c;是JavaWeb三大组件(Servlet、Filter、Listener)之一。 过滤器可以把对资源的请求拦截下来&#xff0c;从而实现一些特殊的功能。 过滤器一般完成一些通用的操作&#xff0c;比如&#xff1a;权限控…

Nuttx学习入门

Nuttx学习 NuttX 是一个实时操作系统 (RTOS)&#xff0c;强调标准合规性和占用空间小。可从 8 位扩展到 64 位微控制器环境&#xff0c;NuttX 中的主要管理标准是 POSIX 和 ANSI 标准。 NuttX 的主要环境依赖性是 (1) GNU make&#xff0c;(2) bash 脚本&#xff0c;和 (3) L…

第三十四章 数论——高斯消元解线性方程组

第三十四章 数论——高斯消元解线性方程组一、高斯消元1、线性方程组2、高斯消元步骤&#xff08;1&#xff09;数学知识铺垫增广矩阵和阶梯矩阵初等变换&#xff08;2&#xff09;高斯消元步骤二、代码模板1、问题&#xff1a;2、代码一、高斯消元 1、线性方程组 我们在小学…

P3884 [JLOI2009]二叉树问题

题目 如下图所示的一棵二叉树的深度、宽度及结点间距离分别为&#xff1a; 深度&#xff1a;44宽度&#xff1a;44结点 8 和 6 之间的距离&#xff1a;88结点 7 和 6 之间的距离&#xff1a;33 其中宽度表示二叉树上同一层最多的结点个数&#xff0c;节点 u, vu,v 之间的距离…

算法工程师需要学习的基础

文章目录应该早点系统地了解算法工程师需要学习的东西的&#xff0c;B站上的up主&#xff1a;梁唐讲的很好&#xff0c;大家可以去看一下&#xff0c;只截了一部分图做一个记录

MySQL5.7 多主一从(多源复制)同步配置

主从复制有如下一些优势&#xff1a; 分担负载&#xff1a;对业务进行读写分离&#xff0c;减轻主库I/O负载&#xff0c;将部分压力分担到从库上&#xff0c;缩短客户查询响应时间。 增加健壮性&#xff1a;在主库出现问题时&#xff0c;可通过多种方案将从库设置为主库&#…

100%全国产龙芯2K1000设计方案

国产工业处理器&#xff0c;龙芯2K1000主板&#xff0c;100%全国产化方案 可实现100%国产元器件方案&#xff0c;国产处理器 信迈2k1000开发板采用龙芯 2k1000处理器&#xff0c;处理器集成 2 个 GS264 处理器核&#xff0c;主频 1GHz&#xff0c;64 位 DDR3 控制器&#xff…

Vue与VueComponent的内置关系

上一节讲到了 Vue.extend 与 VueComponent 的区别&#xff0c;这一节讲一讲 Vue 与 VueComponent的内置关系。 原型与原型链 这里需要用到原型与原型链中的知识点&#xff0c;具体文章链接在这里。js中的原型与原型链 这里只需要理解一个点&#xff0c;那就是构造函数的protot…