Spring开启事务流程和事务相关配置

news2025/1/16 8:11:59

文章目录

  • Spring事务
    • Spring快速入门
    • 事务相关配置

Spring事务

Spring快速入门

事务作用:在数据层保障一系列的数据库操作同成功同失败

Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败

Spring提供了一个接口PlatformTransactionManager用来处理事务

public interface PlatformTransactionManager{
  	void commit(TransactionStatus status) throws TransactionException;
  	void rollback(TransactionStatus status) throws TransactionException;
}

PlatformTransactionManager接口最基本的事务管理实现类DataSourceTransactionManager

public class DataSourceTransactionManager {
    ……
}

案例学习: 模拟银行账户间转账业务

需求:实现任意两个账户间转账操作

需求微缩:A账户减钱,B账户加钱

分析:

①:数据层提供基础操作,指定账户减钱(outMoney),指定账户加钱(inMoney)

②:业务层提供转账操作(transfer),调用减钱与加钱的操作

③:提供2个账号和操作金额执行转账操作

④:基于Spring整合MyBatis环境搭建上述操作

结果分析:

①:程序正常执行时,账户金额A减B加,没有问题

②:账户金额A减执行完成后, 程序出现异常后,转账失败,但是异常之前账户金额A减操作成功,异常之后账户金额B加操作失败,这是有非常大的安全隐患的

实现步骤:

首先创建一个数据库, 有id, name, money三个字段, 以及两条数据

create table tb_account(
    id int primary key auto_increment,
    name varchar(10),
    money varchar(10)
)

insert into tb_account (name, money)
values ("chenyq", 1000), ("zhangsan", 1000);

基于整合Mybatis和Junit环境(不会的可以看前面文章), 创建一个service层接口AccountService

public interface AccountService {
    /**
     * @param out 转出对象
     * @param in 转入对象
     * @param money 转出金额
     */
    void transfer(String out, String in, double money);
}

创建dao层接口AccountDao, 并定义一个加钱和减钱的方法

public interface AccountDao {
    @Update("update tb_account set money = money + #{money} where name = #{name};")
    void inMoney(@Param("name") String name, @Param("money") String money);
    
    @Update("update tb_account set money = money - #{money} where name = #{name};")
    void outMoney(@Param("name") String name, @Param("money") String money);
}

service层AccountService接口的AccountServiceImpl实现类调用数据层方法

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

    public void transfer(String out, String in, double money) {
        accountDao.outMoney(out, money); // 账户减钱
        accountDao.inMoney(in, money); // 账户加钱
    }
}

测试类中进行测试, 可以看到数据库中是修改成功了的

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
    @Autowired
    private AccountService accountService;

    @Test
    public void testTransfer() {
        accountService.transfer("chenyq", "zhangsan", 100);
    }
}

在这里插入图片描述

下面我们在AccountServiceImpl实现类中模拟chenyq账户转钱出去之后, 程序出现异常

@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

    public void transfer(String out, String in, double money) {
        accountDao.outMoney(out, money); // 账户减钱
        int i = 1 / 0; // 模拟程序出现异常
        accountDao.inMoney(in, money); // 账户加钱
    }
}

重新执行测试类, 我们可以发现虽然程序报错, 但是数据库中chenyq账户的money又减少了100

在这里插入图片描述

我们需要开启Spring事务, 让加钱和减钱的操作同时成功或失败, 注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务, Spring开启事务步骤如下

步骤一: 使用@Transactional注解开启任务, 不过我们一般不是在实现类的方法中开启事务, 而是在接口的方法中开启, 降低耦合度

public interface AccountService {
    /**
     * @param out 转出对象
     * @param in 转入对象
     * @param money 转出金额
     */
    @Transactional // 开启事务
    void transfer(String out, String in, double money);
}

步骤二: 在JdbcConfig独立配置文件中, 定义设置一个事务管理器, 并将这个事务管理器交给Spring管理

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
    transactionManager.setDataSource(dataSource);
    return transactionManager;
}

步骤三: 在Spring核心配置文件中, 通过EnableTransactionManagement注解开启Spring对开启事务的注解支持(简单来说, 告知Spring是使用了注解开启事务的)

@Configuration
@ComponentScan("com.chenyq")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MybatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}

到这事务也就开启完成了, 开启事务中的方法同成功同失败, 不会出现因为异常一个业务成功一个业务失败的情况

事务相关配置

事务有如下相关配置:

属性作用示例
readOnly设置是否为只读事务readOnly=true 只读事务
timeout设置事务超时时间timeout = -1(永不超时)
rollbackFor设置事务回滚异常(class)rollbackFor = {NullPointException.class}
rollbackForClassName设置事务回滚异常(String)同上格式为字符串
noRollbackFor设置事务不回滚异常(class)noRollbackFor = {NullPointException.class}
noRollbackForClassName设置事务不回滚异常(String)同上格式为字符串
propagation设置事务传播行为……

使用示例:

@Transactional(readOnly = true, timeout = -1)
void transfer(String out, String in, double money);

有些异常是不参与事务回滚的, 我们需要rollbackFor设置这些异常参与事务回滚

@Transactional(rollbackFor = {NullPointException.class})
void transfer(String out, String in, double money);

如果我们在一个开启事务了的方法1中调用另一个方法2, 我们想要方法1事务回滚时, 方法2不回滚, 就需要设置事务多播行为

@Transactional(propagation = Propagation.REQUIRES_NEW)

事务传播行为还有其他属性

传播属性事务管理员事务协调员
REQUIRED(默认)开启T加入T
新建T2
REQUIRES_NEW开启T新建T2
新建T2
SUPPORTS开启T加入T
NOT_SUPPORTED开启T
MANDATORY开启T加入T
ERROR
NEVER开启TERROR
NESTED设置savePoint,一旦事务回滚,事务将回滚到savePoint处,交由客户响应提交/回滚

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

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

相关文章

Vue可视化项目搭建

安装Nodejs 全局下载Vue项目脚手架 创建项目 运行项目 项目初始化 安装Nodejs 下载地址:https://nodejs.org/zh-cn/ 下载完成之后一路点击下一个安装 全局下载Vue项目脚手架 进入开始菜单以管理员身份运行命令提示符 输入更换镜像源为淘宝源 npm config s…

java线程屏障CyclicBarrier

CyclicBarrier允许一组线程在达到一个公共的屏障点时相互等待。它在涉及固定大小的线程组、并且这些线程必须相互等待的程序中非常有用,CyclicBarrier可以在等待的线程被释放后被重用。 构造方法 CyclicBarrier(int parties) 创建一个新的屏障并设置将要访问这个…

问卷调查样本量的确定方法

我们在进行问卷调查的时候,问卷的收集数量是重要的流程之一。问卷数量取决于几个因素,包括研究的目的和研究的类型。接下来,我们就聊一聊怎么确定所需的调查问卷数量。 1、确定研究目标。 确定所需问卷数量的第一步是明确研究目标。这一步是…

jar包依赖冲突该怎么解决(IT枫斗者)

jar包依赖冲突该怎么解决(IT枫斗者) maven jar包依赖规则 间接依赖路径最短优先一个项目依赖了a和b两个jar包,其中a-b-c1.0,d-e-c1.0,由于c1.0路径最短,所以项目最后使用的jar包是c1.0pom文件中申明顺序优先有人就问…

使用三轴XYZ平台绘制空心字

1. 功能说明 本文示例将实现R312三轴XYZ平台绘制“机器时代”空心字的功能。 2. 电子硬件 在这个示例中,采用了以下硬件,请大家参考: 主控板 Basra主控板(兼容Arduino Uno) 扩展板 Bigfish2.1扩展板 SH-ST步进电机扩展…

2023年最系统的自动化测试,测试开发面试题,10k以下不建议看

鉴于现在严峻的就业形势,千万大学生即将出新手村,今天给大家打包好了2023最能避免薪资倒挂的《面试圣经》。不经一番寒彻骨,怎得梅花扑鼻香。这份面试题,与君共勉! 一、开场白 Q:简单自我介绍一下吧 Q:项…

Bots攻击威胁石油石化企业 瑞数动态安全实现从“人防”到“技防”

近日,中国石油石化企业信息技术交流大会暨油气产业数字化转型高峰论坛在京召开。本届大会由中国石油学会、中国石油、中国石化、中国海油、国家管网、国家能源、中国中化、中国航油、延长石油、中国地质调查局等单位共同主办。 作为我国石油石化行业的盛会&#xf…

论坛现场回顾:维视教育的新工科人才培养 「最佳实践 」

全国高校电子信息类专业教学论坛隆重召开 由教育部高等学校电子信息类专业教学指导委员会主办,苏州大学、清华大学出版社承办的“全国高校电子信息类专业教学论坛”于2023年4月14日-16日在江苏省苏州市隆重开幕,维视教育作为电子信息类教学指导委员会战略…

最优化方法Python计算:连续函数的单峰区间计算

我们知道,闭区间上的一元连续函数必在区间上取得最大值和最小值。实践中我们需要能数值地确定含有 f ( x ) f(x) f(x)的唯一最优解 x 0 x_0 x0​的区间 [ a , b ] [a,b] [a,b]。这里介绍寻求连续函数 f ( x ) f(x) f(x)在一点 x ∗ x^* x∗附近单峰区间的包围算法及…

飞桨paddlespeech语音唤醒推理C实现

上篇(飞桨paddlespeech 语音唤醒初探)初探了paddlespeech下的语音唤醒方案,通过调试也搞清楚了里面的细节。因为是python 下的,不能直接部署,要想在嵌入式上部署需要有C下的推理实现,于是我就在C下把这个方…

Android Stuido中修改项目SDK版本号

通过Android Studio创建项目时,只能选择项目支持的最低SDK版本号,而无法选择当前编译使用的版本号,如图1所示。 图1 选择项目支持的最小版本号 而编译项目的SDK版本号默认是Android Studio安装的最新SDK。如果不想使用最新SDK来编译项目&…

C++入门(3)

C入门 1.auto关键字(C11)1.1. 类型别名的思考1.2. auto简介1.3. auto使用情景1.4. auto的使用细则1.5. auto不能推导的场景 2.函数内联2.1. 问题提出2.2. 概念(关键字——inline)2.3. 特性2.4. 面试题 3. 基于范围的for循环(C11)3…

Python 基础(八):流程控制语句

❤️ 博客主页:水滴技术 🌸 订阅专栏:Python 入门核心技术 🚀 支持水滴:点赞👍 收藏⭐ 留言💬 文章目录 一、条件语句1.1、if1.2、if...else...1.3、if...elif...else... 二、匹配语句2.1、ma…

亚马逊、ebay、temu如何提升产品点击率?测评自养号解析

产品点击率对于店铺销售额的影响至关重要,尤其是在竞争越来越激烈的市场环境中,想要有销量和转化,提高产品listing点击率成为了非常关键的一环。 1. 产品主图 顾客浏览产品时,第一眼看到的就是主图,一张优质的主图更容…

Scala之面向对象

目录 Scala包: 基础语法: Scala包的三大作用: 包名的命名规范: 写包的好处: 包对象: 导包说明: 类和对象: 定义类: 封装: 构造器: 主从…

将项目部署到服务器上,并且使用JMeter测试项目性能

1、前提条件 首先呢,你要有一个有一个项目,并且打包成jar包。然后你要有一台服务器,你可以登录阿里云(国内社区)然后买按量付费的服务用一下,其实服务器就像虚拟机一样,linux命令执行。但是Cen…

操作系统的结构与功能流程

一、用户态和内核态 用户态可以理解为用户模式,内核态理解为内核模式 二、功能流程举例 假设你是一名顾客在一家餐厅用餐,餐厅有一个厨师负责烹饪食物,而你作为顾客只能在餐厅的就餐区域内进行点餐、享用餐点。这里就可以将就餐区域看作用户…

【基于视觉的分割】语义分割初探索:一些经典和先进的算法

写在前面: 有很长时间没有更新学习了,因为在忙着做试验写毕业论文。但是,学习不能停止,从今天开始,换成语义分割方向进行深入学习,有兴趣的小伙伴可以和我一起讨论,也欢迎才进入这个方向学习的…

【Grafana】連接mssql並圖表顯示

【Grafana】連接mssql並圖表顯示 1. 函數2. Demo2.1 Query2.2 Query 3. Awakening1.1 Big Data -- Postgres 1. 函數 Macro exampleReplaced by$__time(dateColumn)An expression to rename the column to time. For example, dateColumn as time$__timeEpoch(dateColumn)An e…

改变思想,拥抱毒瘤,让公司走的更远

牛B的人物,早已经厌倦了中英文混杂,他们更进一步,使用中英文缩写,对普通人进行降维打击。更厉害的,造就新的名词,并科普出去。 有几项技术,我从心底里鄙视和厌恶,但每次在技术方案中…