Java开发学习(二十二)----Spring事务属性、事务传播行为
一、事务配置

上面这些属性都可以在@Transactional注解的参数上进行设置。
readOnly:true只读事务,false读写事务,增删改要设为false,查询设为true。
timeout:设置超时时间单位秒,在多长时间之内事务没有提交成功就自动回滚,-1表示不设置超时时间。
rollbackFor:当出现指定异常进行事务回滚
noRollbackFor:当出现指定异常不进行事务回滚
思考:出现异常事务会自动回滚,这个是我们之前就已经知道的
noRollbackFor是设定对于指定的异常不回滚,这个好理解
rollbackFor是指定回滚异常,对于异常事务不应该都回滚么,为什么还要指定?
这块需要更正一个地方,并不是所有的异常都会回滚事务,比如下面的代码就不会回滚
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
//配置当前接口方法具有事务
public void transfer(String out,String in ,Double money) throws IOException;
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional
public void transfer(String out,String in ,Double money) throws IOException{
accountDao.outMoney(out,money);
//int i = 1/0; //这个异常事务会回滚
if(true){
throw new IOException(); //这个异常事务就不会回滚
}
accountDao.inMoney(in,money);
}
}
出现这个问题的原因是,Spring的事务只会对
Error异常和RuntimeException异常及其子类进行事务回顾,其他的异常类型是不会回滚的,对应IOException不符合上述条件所以不回滚此时就可以使用rollbackFor属性来设置出现IOException异常不回滚
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional(rollbackFor = {IOException.class})
public void transfer(String out,String in ,Double money) throws IOException{
accountDao.outMoney(out,money);
//int i = 1/0; //这个异常事务会回滚
if(true){
throw new IOException(); //这个异常事务就不会回滚
}
accountDao.inMoney(in,money);
}
}
rollbackForClassName等同于rollbackFor,只不过属性为异常的类全名字符串
noRollbackForClassName等同于noRollbackFor,只不过属性为异常的类全名字符串
isolation设置事务的隔离级别
DEFAULT :默认隔离级别, 会采用数据库的隔离级别
READ_UNCOMMITTED : 读未提交
READ_COMMITTED : 读已提交
REPEATABLE_READ : 重复读取
SERIALIZABLE: 串行化
介绍完上述属性后,还有一个事务的传播行为,先看下面的案例
二、转账业务追加日志案例
2.1 需求分析
在上节博客(Java开发学习(二十一)----Spring事务简介与事务角色解析)环境的基础上添加新的需求,完成转账后记录日志。
需求:实现任意两个账户间转账操作,并对每次转账操作在数据库进行留痕
需求微缩:A账户减钱,B账户加钱,数据库记录日志
基于上述的业务需求,我们来分析下该如何实现:
①:基于转账操作案例添加日志模块,实现数据库中记录日志
②:业务层转账操作(transfer),调用减钱、加钱与记录日志功能
需要注意一点就是,我们这个案例的预期效果为:
无论转账操作是否成功,均进行转账操作的日志留痕
2.2 环境准备
环境参考Java开发学习(二十一)----Spring事务简介与事务角色解析,在其基础上,我们继续往下写
步骤1:创建日志表
create table tbl_log(
id int primary key auto_increment,
info varchar(255),
createDate datetime
)
步骤2:添加LogDao接口
public interface LogDao {
@Insert("insert into tbl_log (info,createDate) values(#{info},now())")
void log(String info);
}
步骤3:添加LogService接口与实现类
public interface LogService {
void log(String out, String in, Double money);
}
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
@Transactional
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}
步骤4:在转账的业务中添加记录日志
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
//配置当前接口方法具有事务
public void transfer(String out,String in ,Double money)throws IOException ;
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private LogService logService;
@Transactional
public void transfer(String out,String in ,Double money) {
try{
accountDao.outMoney(out,money);
accountDao.inMoney(in,money);
}finally {
logService.log(out,in,money);
}
}
}
步骤5:运行程序
当程序正常运行,tbl_account表中转账成功,tbl_log表中日志记录成功
当转账业务之间出现异常(int i =1/0),转账失败,tbl_account成功回滚,但是tbl_log表未添加数据
这个结果和我们想要的不一样,什么原因?该如何解决?
失败原因:日志的记录与转账操作隶属同一个事务,同成功同失败
最终效果:无论转账操作是否成功,日志必须保留
三、事务传播行为

对于上述案例的分析:
log方法、inMoney方法和outMoney方法都属于增删改,分别有事务T1,T2,T3
transfer因为加了@Transactional注解,也开启了事务T
前面我们讲过Spring事务会把T1,T2,T3都加入到事务T中
所以当转账失败后,所有的事务都回滚,导致日志没有记录下来
这和我们的需求不符,这个时候我们就想能不能让log方法单独是一个事务呢?
要想解决这个问题,就需要用到事务传播行为,所谓的事务传播行为指的是:
事务传播行为:事务协调员对事务管理员所携带事务的处理态度。
具体如何解决,就需要用到之前我们没有说的propagation属性。
1.修改logService改变事务的传播行为
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
//propagation设置事务属性:传播行为设置为当前操作需要新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}
运行后,就能实现我们想要的结果,不管转账是否成功,都会记录日志。
2.事务传播行为的可选值

Java开发学习(二十二)----Spring事务属性、事务传播行为的更多相关文章
- Java开发学习(三十二)----Maven多环境配置切换与跳过测试的三种方式
一.多环境开发 我们平常都是在自己的开发环境进行开发, 当开发完成后,需要把开发的功能部署到测试环境供测试人员进行测试使用, 等测试人员测试通过后,我们会将项目部署到生成环境上线使用. 这个时候就有一 ...
- Java开发学习心得(二):Mybatis和Url路由
目录 Java开发学习心得(二):Mybatis和Url路由 1.3 Mybatis 2 URL路由 2.1 @RequestMapping 2.2 @PathVariable 2.3 不同的请求类型 ...
- Java开发学习(三十六)----SpringBoot三种配置文件解析
一. 配置文件格式 我们现在启动服务器默认的端口号是 8080,访问路径可以书写为 http://localhost:8080/books/1 在线上环境我们还是希望将端口号改为 80,这样在访问的时 ...
- java jvm学习笔记十二(访问控制器的栈校验机制)
欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...
- Java开发学习(三十四)----Maven私服(二)本地仓库访问私服配置与私服资源上传下载
一.本地仓库访问私服配置 我们通过IDEA将开发的模块上传到私服,中间是要经过本地Maven的 本地Maven需要知道私服的访问地址以及私服访问的用户名和密码 私服中的仓库很多,Maven最终要把资源 ...
- java web学习总结(十二) -------------------Session
一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...
- Java Web学习(十二)Tomcat核心
一.引言 其实按道理来说,学习Java web应该在前面的篇幅就写有关tomcat相关的知识点,不过近期看了一些资料,觉得以前仅仅只是知道用tomcat去发布我的项目,一些细节的东西也没有好好总结,这 ...
- 阿里巴巴 Java 开发手册 (十二)安全规约
1. [强制]隶属于用户个人的页面或者功能必须进行权限控制校验. 说明:防止没有做水平权限校验就可随意访问.修改.删除别人的数据,比如查看他人的私信 内容.修改他人的订单. 2. [强制]用户敏感数据 ...
- Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API
不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...
- Java开发笔记(十二)布尔变量论道与或非
在编程语言的设计之初,它们除了可以进行数学计算,还常常用于逻辑推理和条件判断.为了实现逻辑判断的功能,Java引入了一种布尔类型boolean,用来表示“真”和“假”.该类型的变量只允许两个取值,即t ...
随机推荐
- nodejs使用 svg-captcha 做验证码及验证
一.需求 使用 nodejs 做后端开发,需要请求验证码,在 github 上看到了 svg-captcha 这个库,发现他是将 text 转 svg 进行返回的,安全性也有保证,不会被识别成文字. ...
- [C++STL] vector 容器的入门
vector容器的入门 #include<vector> 创建vector容器的几种方式 数据类型可以是结构体,也能是另外一个容器 vector 的初始化: (1) 创建并声明大小 vec ...
- 将Abp移植进.NET MAUI项目(一):搭建项目
前言 去年12月份做了MAUI混合开发框架的调研,想起来文章里给自己挖了个坑,要教大家如何把Abp移植进Maui项目,由于篇幅限制,将分为三个章节. 将Abp移植进.NET MAUI项目(一):搭 ...
- C++:最大子数组差
最大子数组差 内存限制:128 MiB 时间限制:1000 ms 题目描述: 给定一个整数数组,找出两个不重叠的子数组A和B,使两个子数组和的差的绝对值|SUM(A) - SUM(B) ...
- MTK 平台sensor arch 介绍-hal
MTK 平台sensor arch 介绍-hal 一:整体框架 二:具体流程简介 AP-HAL: (1)init & control flow 我们以前文的originchannel 的 ac ...
- 关于python导入数据库excel数据时出现102, b"Incorrect syntax near '.15562'.DB-Lib error message 20018, severity 1的问题总结
1.对于在使用python导入sqlsever时,出现102, b"Incorrect syntax near '.15562'.DB-Lib error message 20018, se ...
- CVPR2022 | 重新审视池化:你的感受野不是最理想的
前言 本文提出了一种简单而有效的动态优化池操作( Dynamically Optimized Pooling operation),称为DynOPool,它通过学习每一层感受野的最佳大小和形状来优化特 ...
- 【物联网串口服务器通信经验教程】Modbus网关协议转换
在前面的文章中,我们已经详细地介绍了Modbus网关的几种主要类型,今天,就让我们来介绍一下其中简单协议转换的处理过程. 简单协议转换是最常规.最普遍的Modbus网关功能,也是数据处理效率最高Mod ...
- python之单元测试unittest
一.unittest主要内容 主要核心部分:test case, test suite, test runner, test fixture 二.实例 my_class.py文件如下: class F ...
- 『忘了再学』Shell流程控制 — 38、while循环和until循环介绍
目录 1.while循环 2.until循环 1.while循环 对while循环来讲,只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止.和for循环的第二种格式for((初始 ...