声明式事务还是编程式事务,如何选择?

news2025/1/16 13:54:01

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨
👀👀👀 个人博客:小奥的博客
👍👍👍:个人CSDN
⭐️⭐️⭐️:Github传送门
🍹 本人24应届生一枚,技术和水平有限,如果文章中有不正确的内容,欢迎多多指正!
📜 欢迎点赞收藏关注哟! ❤️

文章目录

  • Spring之如何选择事务
    • 1. 编程式事务
    • 2. 声明式事务
      • (1)优点
      • (2)问题
    • 3. 如何选择

Spring之如何选择事务

因为博主之前的实习经历中有使用编程式事务的经历,因为当时是同事给的方案,所以并没有深究为什么不用编程式事务,最近刚好在面试,有面试官问到:为什么不使用声明式事务?因为现在基本很多场景下我们都是直接使用@Transactional注解直接开启事务,所以很少会去使用编程式事务。

所以今天我们就借助这个机会好好来总结一下应该如何选择。

Spring官方文档中对事务的描述如下:

翻译文档链接:传送门

Spring解决了全局和局部事务的弊端。它让应用开发者在任何环境下都能使用一个一致的编程模型。你只需写一次代码,它就可以在不同的环境中受益于不同的事务管理策略。Spring框架同时提供声明式编程式事务管理。大多数用户更喜欢声明式事务管理,我们在大多数情况下都推荐这样做

通过编程式事务管理,开发人员使用Spring框架的事务抽象,它可以在任何底层事务基础设施上运行。通过首选的声明式模型,开发人员通常很少或不写与事务管理有关的代码,因此,不依赖于Spring框架的事务API或任何其他事务API。

下面我们就带大家来学习一下什么是声明式事务和编程式事务。

1. 编程式事务

Spring框架提供了两种编程式事务管理的手段,通过使用:

  • TransactionTemplateTransactionalOperator.
  • 直接实现一个 TransactionManager

Spring团队通常推荐 TransactionTemplate 用于强制性流程中的编程式事务管理, TransactionalOperator 用于响应式代码。第二种方法类似于使用JTA的 UserTransaction API,尽管异常处理没有那么麻烦。

代码示例如下:

public class SimpleService implements Service {

    // single TransactionTemplate shared amongst all methods in this instance
    private final TransactionTemplate transactionTemplate;

    // use constructor-injection to supply the PlatformTransactionManager
    public SimpleService(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
    }

    public Object someServiceMethod() {
        return transactionTemplate.execute(new TransactionCallback() {
            // the code in this method runs in a transactional context
            public Object doInTransaction(TransactionStatus status) {
                updateOperation1();
                return resultOfUpdateOperation2();
            }
        });
    }
}

可以看到,编程式事务在代码中硬编码(不推荐使用) : 通过 TransactionTemplate或者 TransactionManager 手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。

2. 声明式事务

Spring框架的声明式事务管理是通过Spring面向切面编程(AOP)实现的。然而,由于事务方面的代码是随Spring框架的发布而来,并且可以以模板的方式使用,所以一般不需要理解AOP的概念来有效地使用这些代码。

@Transactional 注解来注解你的类,将 @EnableTransactionManagement 添加到你的配置中。基于注解的方法。直接在Java源代码中声明事务语义,使声明更接近于受影响的代码。没有太多的过度耦合的危险,因为无论如何,要以事务方式使用的代码几乎总是以这种方式部署。

代码示例:

// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {

    @Override
    public Foo getFoo(String fooName) {
        // ...
    }

    @Override
    public Foo getFoo(String fooName, String barName) {
        // ...
    }

    @Override
    public void insertFoo(Foo foo) {
        // ...
    }

    @Override
    public void updateFoo(Foo foo) {
        // ...
    }
}

(1)优点

  • 代码简洁,使用方便:从上面的示例代码中可以看到,声明式事务帮我们节省了很多的编码,会自动帮助我们进行事务的开启、提交以及回滚等操作;
  • 对代码没有侵入性:声明式事务管理是基于AOP的方式来实现的,本质就是在目标方法执行前后进行拦截,在目标方法执行前加入或者创建一个事务,在执行方法后,根据实际情况选择提交或者回滚事务。

(2)问题

  • 颗粒度问题:声明式事务有一个局限,就是最小粒度要作用在方法上。也就是说,如果想要给一部分代码添加事务,那就必须这部分代码独立拉出来作为一个方法。
  • 配置问题:因为声明式事务是通过注解的,有些时候还可以通过配置实现,这就会导致一个问题,那就是这个事务有可能被开发者忽略

首先,如果开发者没有注意到一个方法是被事务嵌套的,那么就可能会再方法中加入一些如RPC远程调用、消息发送、缓存更新、文件写入等操作。

我们知道,这些操作如果被包在事务中,有两个问题:

1、这些操作自身是无法回滚的,这就会导致数据的不一致。可能RPC调用成功了,但是本地事务回滚了,可是PRC调用无法回滚了。

2、在事务中有远程调用,就会拉长整个事务。那么久会导致本事务的数据库连接一直被占用,那么如果类似操作过多,就会导致数据库连接池耗尽。

  • 事务失效:声明式事务虽然看上去帮我们简化了很多代码,但是有一些场景会使得声明式事务失效,这也是一个比较常见的八股文了,如下:

Spring框架提供了非常方便的事务管理机制,但是在某些情况下,Spring事务会失效。

(1)方法非public。如果一个方法不是public修饰的,那么Spring无法代理这个方法,Spring官方文档中有明确的说明,@Transactional只有在修饰public方法时才会生效。修改pretected、private或者保内可见的方法均不会生效。

(2)事务方法被final、static关键字修饰。事务方法被final修改会防止子类重写该方法,从而无法进行动态代理,事务方法被static修改会使得该方法属于类而不是对象,因此也无法进行动态代理。

(3)方法自调用。当一个类中的一个方法调用同一个类中的另一个@Transactional方法时,这种情况被称为方法自调用,在这种情况下,事务控制将无法正常工作。因为事务代理对象在外部调用时才会被创建,如果一个方法在同一个类中调用另一个方法,实际上是在当前实例中进行调用,而不是通过代理对象调用。

(4)异常被捕获。Spring默认只对未被捕获的异常进行回滚,如果异常被捕获并处理了,那么Spring无法感知到异常的存在,也就无法进行回滚,因此,如果需要事务回滚,必须确保异常未被捕获并没有被处理。

(5)没有被Spring管理。只有在Spring容器中管理的Bean上的@Transactional注解才会生效,如把@Service注解注释掉,这个类就不会被加载成为一个Bean,在该对象的方法上添加@Transactional注解将不会有任何效果。

(6)数据库不支持事务。Spring事务是通过底层的数据库事务实现的。如果底层数据库不支持事务,那么Spring自然无法实现事务管理,如果需要使用事务,选择支持事务的数据库引擎,如MySQL的InnoDB引擎。

3. 如何选择

关于如何选择事务的使用方式,我们可以从@Transactional失效的场景来考虑,如果考虑到后续可能无法避免事务失效的问题,那么我建议还是最好使用编程式事务,因为硬编码其实简单粗暴,不管三七二十一,强制让事务执行。

其实关于@Transactional的用法,Java手册中也有对应的规范如下:

在这里插入图片描述

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

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

相关文章

[善用佳软]推荐掌握小工具:Json解析的命令行工具jq

前言: 我们在各种生产环境或者开发测试环境中,一定遇到有很多信息都是使用JSON串或者文本文件作为输入的。在没有JQ命令行工具之前,我们要从中获取真正的输入,大都把它复制到文本里头,然后使用文本编辑器进行加工整理…

WSL2执行nvidia-smi报错:Command ‘nvidia-smi‘ not found, but can be installed with

报错信息: Command nvidia-smi not found, but can be installed with: sudo apt install nvidia-utils-390 # version 390.157-0ubuntu0.22.04.2, or sudo apt install nvidia-utils-418-server # version 418.226.00-0ubuntu5~0.22.04.1 sudo apt insta…

LeetCode 热题 100 | 回溯(二)

目录 1 39. 组合总和 2 22. 括号生成 3 79. 单词搜索 菜鸟做题,语言是 C,感冒快好版 关于对回溯算法的理解请参照我的上一篇博客; 在之后的博客中,我将只分析回溯算法中的 for 循环。 1 39. 组合总和 题眼:c…

程序员的知识宝库,100+开源书籍、文档

公众号:【可乐前端】,每天3分钟学习一个优秀的开源项目,分享web面试与实战知识,也有全栈交流学习摸鱼群,期待您的关注! 每天3分钟开源 hi,这里是每天3分钟开源,很高兴又跟大家见面了&#xff0…

代码随想录刷题笔记 Day 52 | 打家劫舍 No.198 | 打家劫舍 II No.213 | 打家劫舍III No.337

文章目录 Day 5201. 打家劫舍&#xff08;No. 198&#xff09;<1> 题目<2> 笔记<3> 代码 02. 打家劫舍 II&#xff08;No. 213&#xff09;<1> 题目<2> 笔记<3> 代码 03.打家劫舍III&#xff08;No. 337&#xff09;<1> 题目<2&g…

RocketMQ学习笔记三(黑马)大神级

课程来源:6.RocketMQ安装_哔哩哔哩_bilibili (时长:19.5h) 讲解版本:4.5版本(我是以4.8版本实践的) 目录 第一部分 核心功能 第1章 RocketMQ的下载、安装、启动和测试(Linux环境) 启动: 测试: 第2章 RocketMQ集群搭建 2.1 集群特点 2.2 集群模式 2.3 双主…

HTML_CSS练习:HTML注释

一、代码示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>HTML注释</title> </head> <body><marquee loop"1">马龙强<!--下面的输入框是可以滚动的&#x…

新手必看!YouTube运营教程:你需要的策略、工具和技巧

欢迎来到 YouTube 的世界&#xff01;对于跨境电商和海外社媒营销人员来说&#xff0c;YouTube 是一个充满机遇的宝地。无论你是希望通过视频内容扩大品牌影响力&#xff0c;还是想要抓住全球买家的注意力&#xff0c;掌握YouTube运营的基础是你成功的第一步。本篇教程将为你揭…

云与云计算:从传统到云端的IT资源变革

云&#xff1a;从分散到集约&#xff0c;资源服务化的新模式 让我们先通过一个生活化的场景来理解“云”这一概念。几十年前&#xff0c;诸如农村地区的居民需要自给自足&#xff0c;比如在自家院子里打井取水&#xff0c;冬季烧煤取暖&#xff0c;一切满足自己生活需要的都要…

健康消费需求持续上涨,品牌如何抓住机遇

近年来&#xff0c;国内“大健康”时代徐徐展开&#xff0c;居民消费热度不断攀升&#xff0c;主动健康消费已经成为新的增长点&#xff0c;然而健康行业的内容由于专业性较高&#xff0c;传播范围有限导致无法直接触达用户。在当下的传播环境中&#xff0c;品牌应该如何抓住机…

百万级excel导入导出

项目目录结构&#xff1a; * 导入思路&#xff1a; excel拆分为多个sheet&#xff0c;开启20个线程分别处理20个sheet&#xff0c;采用批量插入的方式入库 * 导出思路&#xff1a; 开启20个线程分页读取数据&#xff0c;放入到map中&#xff0c;CountDownLatch保证并发安全…

C++(14)——vector

目录 vector是什么&#xff1f; vector的使用 vector的构造 vector iterator的使用 vector空间增长问题 vector的增删查改 push_back和pop_back operator[] 总结 vector是什么&#xff1f; vector是什么呢&#xff1f;按照英文来说&#xff0c;vector的英文是向量、矢…

Lord 3DMCV7-AHRS 时间同步硬件触发设置

目的:通过FPGA发送脉冲触发IMU采集数据。FPGA发送脉冲时,IMU才有数据产生。 FPGA与IMU的硬件接线就不讲了,这里主要说明的是IMU的设置以及ROS驱动的config文件更改。 1. WIN上位机设置 通过IMU在WINDOWS的上位机SensorConnect对IMU的GPIO、波特率等基本功能进行设值,具体…

视频素材软件app免费网站哪里找?

在如今的短视频时代&#xff0c;为了满足视频素材创作者们的需求&#xff0c;有很多提供免费短视频素材下载的应用程序可供选择。 接下来&#xff0c;我们将对视频素材软件app免费网站哪里找做出介绍 可以考虑以下几个视频素材软件app免费 蛙学网 提供多元化视频&#xff0c…

面试常问:你在项目中遇到了哪些比较棘手的问题?怎么解决的?

你在项目中遇到了哪些比较棘手的问题?怎么解决的&#xff1f;这个问题是面试官经常会问的一个问题。 如果你回答我在项目中没有怎么遇到&#xff0c;那么面试官会觉得你什么都不会&#xff0c;对项目了解也不够深入也没有负责什么项目。 面试官其实还挺关心的是应聘者的问题…

注意力机制Attention、CA注意力机制

一、注意力机制 产生背景&#xff1a; 大数据时代&#xff0c;有很多数据提供给我们。对于人来说&#xff0c;可以利用重要的数据&#xff0c;过滤掉不重要的数据。那对于模型来说&#xff08;CNN、LSTM&#xff09;&#xff0c;很难决定什么重要、什么不重要&#xff0c;因此…

APP开发如何成功上架到应用市场?

在当今移动互联网时代&#xff0c;开发一款优秀的APP并将其成功上架到各大应用市场是每个开发者梦寐以求的成就之一。但是&#xff0c;不同类型的APP在上架过程中可能会面临各种不同的挑战和要求。 APP上架到应用市场一般包括以下几个流程&#xff1a; 步骤一&#xff1a;开发及…

web部署 三

案例: 1/在其中一个网站目录下创建\software文件夹&#xff0c;里面放txtppt/mp4/iso,文件类型。 2/web站点目录浏览启动应用。 3/用win10客户机浏览software目录下文件&#xff0c;并下载。txtppt/mp4/iso&#xff0c;发现问题并解决。 首先我们先建立一个software的文件夹并…

Linux控制台、终端、Shell 的历史

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; ①微思网络&#xff0c;始于2002年&#xff01;专注IT认证培训22年。 ② 领取学习资料/课程咨询&#xff1a;小美老师&#xff08;wx&#xff09;&…

工作中Git如何切换远程仓库地址

工作中Git如何切换远程仓库地址 部门之前的仓库不用了&#xff0c;重新建了一个仓库&#xff0c;但是上传代码还是上传到了之前的仓库里面了&#xff0c;所以得进行修改&#xff0c;下面将修改地址的方法进行操作。 方法一、直接修改远程仓库地址 查看当前远程仓库地址 git …