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 ... 
随机推荐
- 709. To Lower Case - LeetCode
			Question 709. To Lower Case Sollution 题目大意:字符串大写转小写 思路: 直接调用Java API函数 字符串转char数组,遍历数组,判断如果大写就转小写 Ja ... 
- 274. H-Index - LeetCode
			Question 274. H-Index Solution 题目大意: 论文里的 h 因子判定,题目的意思可能有点晦涩.h 因子是评判学术成就的一种重要方法,h 因子越高越好,h 因子兼顾研究学术人 ... 
- forms组件补充与ModelForm简单使用与cookie与session
			目录 forms组件钩子函数 forms组件字段参数 字段参数 validators详解 choices详解 widget详解 forms组件字段类型 ModelForm简单使用 cookie与ses ... 
- typescript 的安装和检测是否安装成功
			全局安装typescript npm install -g typescript 检查typescript是否安装成功 tsc -v 
- Pandas:添加修改、高级过滤
			1.添加修改数据 Pandas 的数据修改是进行赋值,先把要修改的数据筛选出来,然后将同结构或者可解包的数据赋值给它: 修改数值 df.Q1 = [1, 3, 5, 7, 9] * 20 # 就会把值 ... 
- Java的标识符与关键字
			目录 Java关键字 总表:java关键字共53个(其中包含两个保留字const,goto) Java标识符 定义 组成 命名规则 视频课程 Java关键字 Java关键字是电脑语言里事先定义的,有特 ... 
- 关于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 ... 
- 2021.04.24【NOIP提高B组】模拟 总结
			2021.04.24[NOIP提高B组]模拟 总结 T1 题意:有一圈数.两两之间有加法或乘法操作, 问你开始断掉那条边使得剩下的序列经过某种操作后的值最大 看上去是个区间 dp .然后直接断环成列, ... 
- BUUCTF-easycap
			easycap 看这个题目应该是流量包来的,wireshark打开即可.没什么特征,直接打开第一个包发现flag 
- 使用aggregation API扩展你的kubernetes API
			Overview What is Kubernetes aggregation Kubernetes apiserver aggregation AA 是Kubernetes提供的一种扩展API的方法 ... 
