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

news/2024/11/29 1:55:40/

文章目录

  • 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 {@Autowiredprivate 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 {@Autowiredprivate AccountService accountService;@Testpublic void testTransfer() {accountService.transfer("chenyq", "zhangsan", 100);}
}

在这里插入图片描述

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

@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate 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.ppmy.cn/news/41736.html

相关文章

零基础学习Java 08

目录 继承 super关键字 继承中构造方法的关系 继承使用场景 继承的设计技巧 多态 多态中的成员访问特点 继承 继承:多个类中存在相同属性(成员变量)和行为(成员方法)时,将这些内容抽取到单独一个类中…

CS5463 DP转HDMI8K30Hz转换芯片规格书|CS5466 typec转HDMI8K30Hz (4K144Hz)转换芯片规格书

1.CS5463/CS5266概述 CS5463/CS5466是一款高性能的Type-C/DisplayPort1.4到HDMI2.1协议转换器,通过Type-C/D DisplayPort链路接收视频和流,并转换为支持TMDS或FRL输出信令的HDM。DP接收器在2个通道上支持高达8.1 Gbps的链路速率。HDMI输出端口可以作为T…

类的相关知识(一)

目录 OOP(面向对象编程) 区别 面向过程 面向对象 类 成员函数 类的作用域 类的大小 this指针 OOP(面向对象编程) 本质上是一种编程思想,通过把我们编程中遇到的事物抽象成对象来编程 区别 面向过程 struc…

SQL Day01

1.关系型数据库的特点 理论基础:关系代数(集合论、一阶逻辑、关系运算) 具体表象:用二维表装数据 ​ - 表 - table / entity - relation ​ - 列 - column / field - attribute ​ - 行 - row / record - tuple ​ - 列的数量 - …

不完整数据下视听情感识别的自注意融合

Self-attention fusion for audiovisual emotion recognition with incomplete data 译文:不完整数据下视听情感识别的自注意融合 摘要:在本文中,我们以视听情感识别为例,考虑了多模态数据分析的问题。我们提出了一种能够从原始…

Excel快捷键

ctrlQ 快速分析,对数据进行快速分析,如求和,图表、格式化数据等 ctrlT 转化为超级表,超级表的功能很多,很便捷 ctrlE 快速填充,能够根据规律自动填充对应的数据提出或拼接 ctrl;ctrlshift&#…

华硕ROG|玩家国度 冰刃7双屏 GX650PY Windows11原厂预装系统 工厂模式恢复安装带ASUSRecevory一键还原

华硕ROG|玩家国度 冰刃7双屏 GX650PY Windows11原厂预装系统 工厂模式恢复安装带ASUSRecevory一键还原 文件地址:https://pan.baidu.com/s/1snKOsH3OMl3GZLqeAf-GLA?pwd8888 华硕工厂恢复系统 ,安装结束后带隐藏分区以及机器所有驱动软件 需准备一个…

C中的预处理,宏

🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才下…