@Transactional注解属性(1)

文章目录

1、readOnly

2、timeout

3、rollbackFor和rollbackForClassName


readOnly:事务只读,指对事务性资源进行只读操作。如下代码:

//立即购买@Override@Transactional(readOnly=true)public boolean insert(String userId,String bookId, int count) {if(bookDao.enough(bookId, count)) {//书籍足够//书籍表库存递减bookDao.update(bookId, count);}double price = bookDao.getPrice(bookId);double total = price*count;if(moneyDao.enough(userId, total)) {//余额足够//订单表添加数据Coupon coupon = new Coupon();coupon.setId(UUID.randomUUID().toString());coupon.setUserId(userId);coupon.setBookId(bookId);coupon.setTotal(total);couponDao.insert(coupon);//钱包表递减moneyDao.update(userId, total);}return true;}

如以上代码所示,在@Transactional注解中添加了readOnly=true,但@Transactional注解修饰的方法涉及数据的修改,因此抛出如下异常:


timeout:设置一个事务所允许执行的最长时长(单位:秒),如果超过该时长且事务还没有完成,则自动回滚事务且出现org.springframework.transaction.TransactionTimedOutException异常,如下代码:

//立即购买@Override@Transactional(timeout=3)public boolean insert(String userId,String bookId, int count) {if(bookDao.enough(bookId, count)) {//书籍足够//书籍表库存递减bookDao.update(bookId, count);}double price = bookDao.getPrice(bookId);double total = price*count;try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}if(moneyDao.enough(userId, total)) {//余额足够//订单表添加数据Coupon coupon = new Coupon();coupon.setId(UUID.randomUUID().toString());coupon.setUserId(userId);coupon.setBookId(bookId);coupon.setTotal(total);couponDao.insert(coupon);//钱包表递减moneyDao.update(userId, total);}return true;}

Thread.sleep(4000)会使得当前事务4秒之后结束,该时长超出了所允许的最长时长,因此事务自动回滚,书籍表库存递减操作无效,程序出现异常如下所示:


rollbackFor和rollbackForClassName:指定对哪些异常回滚事务。默认情况下,如果在事务中抛出了运行时异常(继承自RuntimeException异常类),则回滚事务;如果没有抛出任何异常,或者抛出了检查时异常,则依然提交事务。通过rollbackFor和rollbackForClassName就可以根据需要人为控制事务在抛出某些运行时异常时仍然提交事务,或者在抛出某些检查时异常时回滚事务。 如下代码所示:

此时MoneyException为运行时异常

package com.jd.exception;public class MoneyException extends RuntimeException {private static final long serialVersionUID = 669695292705313042L;public MoneyException(String message) {super(message);}
}
//立即购买@Override@Transactionalpublic boolean insert(String userId,String bookId, int count) {if(bookDao.enough(bookId, count)) {//书籍足够//书籍表库存递减bookDao.update(bookId, count);}double price = bookDao.getPrice(bookId);double total = price*count;if(moneyDao.enough(userId, total)) {//余额足够//订单表添加数据Coupon coupon = new Coupon();coupon.setId(UUID.randomUUID().toString());coupon.setUserId(userId);coupon.setBookId(bookId);coupon.setTotal(total);couponDao.insert(coupon);//钱包表递减moneyDao.update(userId, total);}return true;}

书籍表中有6本书籍,每本书10元,一个人钱包有10元,欲买5本,则该行代码抛出MoneyException异常,但由于该异常为运行时异常,所以回滚事务,即左边图片“bookDao.update(bookId, count);”行代码执行失效!,如下所示:


此时MoneyException为检查时异常,且立即购买代码中不加rollbackFor注解属性

package com.jd.exception;public class MoneyException extends Exception {private static final long serialVersionUID = 669695292705313042L;public MoneyException(String message) {super(message);}
}
//立即购买@Override@Transactionalpublic boolean insert(String userId,String bookId, int count) throws MoneyException {if(bookDao.enough(bookId, count)) {//书籍足够//书籍表库存递减bookDao.update(bookId, count);}double price = bookDao.getPrice(bookId);double total = price*count;if(moneyDao.enough(userId, total)) {//余额足够//订单表添加数据Coupon coupon = new Coupon();coupon.setId(UUID.randomUUID().toString());coupon.setUserId(userId);coupon.setBookId(bookId);coupon.setTotal(total);couponDao.insert(coupon);//钱包表递减moneyDao.update(userId, total);}return true;}

书籍表中有10本书籍,每本书10元,一个人钱包有10元,欲买5本,则该行代码抛出MoneyException异常,但由于该异常为检查时异常,所以依然提交事务,即“bookDao.update(bookId, count);”行代码执行生效!,结果如下:

数量依旧减少了,不符合实际,没有进行事务回滚


此时MoneyException为检查时异常,且立即购买代码中加rollbackFor注解属性

package com.jd.exception;public class MoneyException extends Exception {private static final long serialVersionUID = 669695292705313042L;public MoneyException(String message) {super(message);}
}
//立即购买@Override@Transactional(rollbackFor=MoneyException.class)public boolean insert(String userId,String bookId, int count) throws MoneyException {if(bookDao.enough(bookId, count)) {//书籍足够//书籍表库存递减bookDao.update(bookId, count);}double price = bookDao.getPrice(bookId);double total = price*count;if(moneyDao.enough(userId, total)) {//余额足够//订单表添加数据Coupon coupon = new Coupon();coupon.setId(UUID.randomUUID().toString());coupon.setUserId(userId);coupon.setBookId(bookId);coupon.setTotal(total);couponDao.insert(coupon);//钱包表递减moneyDao.update(userId, total);}return true;}

书籍表中有10本书籍,每本书10元,一个人钱包有10元,欲买5本,则该行代码抛出MoneyException异常,该异常为检查时异常,添加@Transactional(rollbackFor=MoneyException.class)注解,指定MoneyException回滚事务,所以不会提交事务,即“bookDao.update(bookId, count);”行代码执行不生效!,结果如下:

书籍数量不变,事务回滚

注意:下例红框中代码不能try-catch处理异常,否则即便@Transactional注解中添加了rollbackFor=MoneyException.class,事务也不会回滚,如下代码:

结果如下:事务依然提交

@Transactional注解属性(1)相关推荐

  1. 一口气说出 6 种 @Transactional 注解的失效场景

    一.事务 事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种. 编程式事务:是指在代码中手动的管理事务的提交.回滚等操作,代码侵入性比较强, ...

  2. @Transactional注解在什么情况下失效?

    引言 1.@Transactional 注解相信大家并不陌生,平时开发中很常用的一个注解,它能保证方法内多个数据库操作要么同时成功.要么同时失败. 2.使用@Transactional注解时需要注意许 ...

  3. @getmapping注解的作用_一口气说出6种,@Transactional注解的失效场景

    作者:程序员内点事 引言 昨天公众号粉丝咨询了一个问题,说自己之前面试被问@Transactional注解哪些场景下会失效,一时语塞致使面试失败.所以今天简单的和大家分享一下@Transactiona ...

  4. @Transactional 注解的失效场景

    作者:码农开花 链接:https://zhuanlan.zhihu.com/p/351260443 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 引言 有人咨询了一 ...

  5. 面试一口气说出Spring的声明式事务@Transactional注解的6种失效场景

    一.Spring事务管理的两种方式 事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种. 编程式事务:是指在代码中手动的管理事务的提交.回滚 ...

  6. spring声明式事务管理方式( 基于tx和aop名字空间的xml配置+@Transactional注解)

    1. 声明式事务管理分类 声明式事务管理也有两种常用的方式, 一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解. 显然基于注解的方式更简单易用,更清爽. ...

  7. 一口气说出 6种 @Transactional 注解失效场景

    引言 昨天公众号粉丝咨询了一个问题,说自己之前面试被问@Transactional注解哪些场景下会失效,一时语塞致使面试失败.所以今天简单的和大家分享一下@Transactional相关的知识. @T ...

  8. @getmapping注解的作用_@Transactional注解失效了?你遇到的是这6种场景吧!

    引言 昨天公众号粉丝咨询了一个问题,说自己之前面试被问@Transactional注解哪些场景下会失效,一时语塞致使面试失败.所以今天简单的和大家分享一下@Transactional相关的知识. @T ...

  9. 聊一聊Spring中@Transactional注解及其失效的七种场景

    文章目录 一.事务(基于AOP) 二.@Transactional介绍 三.@Transactional失效场景 说明:当我准备写我知道的那几个场景时,我发现有人比我写的更好,关键是好得多,于是我就用 ...

  10. 常见的 @Transactional 注解,你确定用对了吗?

    @Transactional属性详解 声明式事务管理建立在AOP之上的.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务. 简而 ...

最新文章

  1. Weka 3.7.12源码学习、阅读、分析(1)
  2. html5判断设备的动作
  3. 给选择模型的子模型添加COL
  4. 程学旗 计算机,徐明伟-青年科学家奖-中国计算机学会
  5. labelimg如何调整框的颜色_PS学习之旅:如何更好调整画面明暗?明度、色阶详细介绍,收藏...
  6. 【认证课程】NP理论复习之IS-IS
  7. sql:命名管道管道程序_学习SQL:命名约定
  8. javaio_java------io基础(一)
  9. android screenshot 命令,android 截图,视频录制命令 screencap screenrecord screenshot
  10. 如何解决'chromedriver' executable needs to be in PATH.的问题
  11. 计算机主机硬件部分组成,台式电脑主机的硬件组成部分
  12. 优动漫PAINT入门宝典(图层篇)——矢量图层
  13. 阿里云推出节省计划的每小时承诺消费怎么样?
  14. 铁矿石需求量matlab代码,铁矿石期货市场分析
  15. 448. Find All Numbers Disappeared in an Array(找到所有数组中消失的数字)
  16. 【IT圈内事】2019互联网企业100强
  17. 自动驾驶技术(2)--智能车辆导航技术概述
  18. 从底层结构开始学习FPGA(5)----移位寄存器
  19. 堪破而不沉沦,一笑以渡
  20. 网络安全--红队资源大合集

热门文章

  1. 带你快速玩转canvas——写个折线图
  2. Java SPI机制简介
  3. 40页PPT勾画“互联网颠覆性思维”----诠释互联网思维
  4. 系统架构升级建议书(1)
  5. 运用C#创建一个.Net下的Web Service
  6. webmin的vsftp插件
  7. 关于RabbitMQ Queue Argument的简介
  8. Linux设备管理(三):sysfs文件系统的功能及其应用
  9. C# Log4Net简单使用方法
  10. C/C++经典程序训练1---最大公约数与最小公倍数 SDUT ACM