spring事务回滚异常
很多同学在进行编程学习时缺乏系统学习的资料。本页面基于spring事务回滚异常内容,从基础理论到综合实战,通过实用的知识类文章,标准的编程教程,丰富的视频课程,为您在spring事务回滚异常相关知识领域提供全面立体的资料补充。同时还包含 safari浏览器、samba、SAMP 的知识内容,欢迎查阅!
spring事务回滚异常相关知识
-
spring 事务深入 -事务失效事务失效的几种原因:1.spring的事务注解@Transactional只能放在public修饰的方法上才起作用,如果放在其他非public(private,protected)方法上,虽然不报错,但是事务不起作用2.如使用mysql且引擎是MyISAM,则事务会不起作用,原因是MyISAM不支持事务,可以改成InnoDB引擎。 3.默认情况下,Spring会对unchecked异常进行事务回滚;如果是checked异常则不回滚。什么是unchecked异常,什么是checked异常?java里面将派生于Error或者RuntimeException(比如空指针,1/0)的异常成为unchecked异常,其他继承自java.lang.Exception的异常统称为checked Exception,如IOException、TimeOutException等 通俗点讲就是,写的代码出现了空指针异常,会被回滚,而文件读写,网络出问题,spring就没法回滚了。 写代码的时候,有些IOException我们的
-
try catch对Spring事务的影响一、Spring 的默认事务机制,当出现unchecked异常时候回滚,checked异常的时候不会回滚。 异常中unchecked异常包括error和runtime异常。需要try catch或向上抛出的异常,为checked异常比如IOException,也就是说程序抛出runtime异常的时候才会进行回滚,其他异常不回滚,可以配置设置所有异常回滚: @Transactional(rollbackFor = { Exception.class }) 当有try catch后捕获了异常,事务不会回滚。如果不得不在service层写try catch 需要catch后 throw new RuntimeException 让
-
spring boot事务与缓存spring boot事务机制 spring支持声明式事务,用@Tracsational注解在方法上表明该方法需要事务支持。被注解的方法在被调用时开启一个新的事务,当方法无异常结束时,spring会提交这个事务。 属性:propagation,定义事务的生命周期;isolation,隔离,决定事务的完整性;timeout,事务过期时间;readonly,只读事务;rollback,指定哪些异常可以引起事务回滚;norollback,哪些异常不可以引起事务回滚。 spring data JPA对所有的默认方法都开启了事务支持。 1.实体类Person 2.repository实体类PersonRepository 3.service: public class DemoServiceImpl implements DemoService{ @Autowired PersonRepository personRepository; @Transactional(rollbackFor=
-
聊聊spring事务在异常场景下发生不按套路出牌的事儿前言 最近看了一下网上总结的spring事务失效的N个场景,网上列出来的场景有如下 数据库引擎不支持事务 没有被 Spring 管理 方法不是 public 的 自身调用问题 数据源没有配置事务管理器 不支持事务 异常被吃了 异常类型错误 其中有条异常被吃了,会导致事务无法回滚,这个引起我的好奇,是否真的是这样,刚好也没写文素材了,就来聊聊事务与异常在某些场景产生的化学反应 示例素材 1、一张没啥业务含义的表,就单纯用来演示用 CREATE TABLE `tx_test` ( `id` bigint NOT
spring事务回滚异常相关课程
spring事务回滚异常相关教程
- 4.2 例2 回滚事务 事务提交和事务回滚是一对互斥操作,事务回滚后,事务之前的操作都将失效。请书写 SQL 语句,通过一个事务向imooc_user表插入一个用户,用户名为dell,年龄为21,并回滚事务。分析:先显示通过 BEGIN 开始一个事务,然后使用 INSERT 语句插入用户,再通过 ROLLBACK 回滚事务即可。语句:整理可得语句如下:BEGIN;INSERT INTO imooc_user(id,username,age) VALUES (7,'dell',21);ROLLBACK;执行成功后,dell 并未被插入到 imooc_user 表中,可见 ROLLBACK 的确撤销了之前的数据操作。
- 6.1 抛出检查型异常时事务失效 首先了解下异常类型:Exception 受检查的异常:在程序中必须使用 try…catch 进行处理,遇到这种异常不处理,编译器会报错。例如 IOException 。RuntimeException 非受检查的异常:可以不使用 try…catch 进行处理。例如常见的 NullPointerException 。在大多数人潜意识中,只要发生异常,事务就应该回滚,实际上使用 @Transactional 时,默认只对非受检查异常回滚。例如:实例: @Transactional // 实现事务 public int createOrder(Long goodsId, Long count) { // 锁定商品库存 GoodsDo goods = goodsDao.selectForUpdate(goodsId); // 扣减库存 Long newNum = goods.getNum() - count; goods.setNum(newNum); goodsDao.update(goods); if (count > goods.getNum()) { // 非受检查异常抛出时,会回滚 throw new RuntimeException(); } // 生成订单 OrderDo order = new OrderDo(); order.setGoodsId(goodsId); order.setCount(count); int affectRows = orderDao.insert(order); return affectRows; }实例: @Transactional // 实现事务 public int createOrder(Long goodsId, Long count) throws Exception { // 锁定商品库存 GoodsDo goods = goodsDao.selectForUpdate(goodsId); // 扣减库存 Long newNum = goods.getNum() - count; goods.setNum(newNum); goodsDao.update(goods); if (count > goods.getNum()) { //注意!此处为受检查的异常,就算抛出也不会回滚 throw new Exception(); } // 生成订单 OrderDo order = new OrderDo(); order.setGoodsId(goodsId); order.setCount(count); int affectRows = orderDao.insert(order); return affectRows; }如果想实现只要抛出异常就回滚,可以通过添加注解 @Transactional(rollbackFor=Exception.class) 实现。实例: @Transactional(rollbackFor = Exception.class) // 抛出异常即回滚 public int createOrder(Long goodsId, Long count) throws Exception { // 锁定商品库存 GoodsDo goods = goodsDao.selectForUpdate(goodsId); // 扣减库存 Long newNum = goods.getNum() - count; goods.setNum(newNum); goodsDao.update(goods); if (count > goods.getNum()) { throw new Exception(); } // 生成订单 OrderDo order = new OrderDo(); order.setGoodsId(goodsId); order.setCount(count); int affectRows = orderDao.insert(order); return affectRows; }OK,我们将在测试类中,将购买数量设为大于库存数量的 100 ,然后一次测试上面三种情况,就能验证上面的说法了。实例:/** * 订单测试 */@SpringBootTestclass OrderTest { @Autowired private OrderService orderService; /** * 创建订单测试 */ @Test void testCreateOrder() throws Exception { // 购买id为1的商品1份 int affectRows = orderService.createOrder(1L, 100L); assertEquals(1, affectRows); }}
- 4.3 例3 回滚且提交事务 前面谈到,事务的回滚是可以指定保存点的,因此我们可以只回滚部分操作,提交其它操作。如下:BEGIN;INSERT INTO imooc_user(id,username,age) VALUES (8,'stark', 20);SAVEPOINT savepoint1;INSERT INTO imooc_user(id,username,age) VALUES (9,'alice', 20);ROLLBACK TO savepoint1;COMMIT;上面的 SQL 语句的大致执行流程如下:BEGIN 显示的开启了一个事务。向 imooc_user 表中插入了用户 stark ,并且通过 SAVEPOINT 新建了保存点 savepoint1。又向 imooc_user 中插入了另外一个用户 alice。通过 ROLLBACK 将事务回滚到了 savepoint1,即第2个插入语句将会失效。提交事务。执行成功后,数据如下:+----+----------+-----+| id | username | age |+----+----------+-----+| 8 | stark | 20 |+----+----------+-----+从结果中可以得出,alice 用户并没有插入成功,这与我们的分析一致,也验证了事务的强大。
- 5. 分布式事务 采用多数据源之后,事务的实现方式也随之发生变化。当某个数据源操作出现异常时,该数据源和其他数据源的事务都需要回滚。这种涉及多个数据源的事务,称为分布式事务,接来下我们就来具体实现一下。
- 6.2 一个事务方法调用另一个事务方法时失效 先看下面的实例,我们修改下 OrderService 类,通过一个事务方法调用 createOrder 方法。实例:/** * 订单服务类 */@Service // 注册为服务类public class OrderService { @Autowired private GoodsDao goodsDao; @Autowired private OrderDao orderDao; @Transactional // 开启事务 public int startCreateOrder(Long goodsId, Long count) throws Exception { return this.createOrder(goodsId, count); } /** * 下单 * * @param goodsId 购买商品id * @param count 购买商品数量 * @return 生成订单数 */ @Transactional(rollbackFor = Exception.class) // 抛出异常即回滚 public int createOrder(Long goodsId, Long count) throws Exception { // 锁定商品库存 GoodsDo goods = goodsDao.selectForUpdate(goodsId); // 扣减库存 Long newNum = goods.getNum() - count; goods.setNum(newNum); goodsDao.update(goods); if (count > goods.getNum()) { // 非受检查异常抛出时,会回滚 throw new Exception(); } // 生成订单 OrderDo order = new OrderDo(); order.setGoodsId(goodsId); order.setCount(count); int affectRows = orderDao.insert(order); return affectRows; }}此时我们在测试类中通过 startCreateOrder 方法再去调用 createOrder 方法,代码如下:实例:/** * 订单测试 */@SpringBootTestclass OrderTest { @Autowired private OrderService orderService; /** * 创建订单测试 */ @Test void testCreateOrder() throws Exception { // 购买id为1的商品1份 int affectRows = orderService.startCreateOrder(1L, 100L); assertEquals(1, affectRows); }}startCreateOrder 和 createOrder 方法都是事务方法,且这两个方法事务特性不同 (一个没有 rollbackFor=Exception.class),如果我们调用 startTransaction 方法,则 createOrder 中的事务并不会生效。也就是说,如果在同一个类中,一个事务方法调用另一个事务方法,可能会导致被调用的事务方法的事务失效!这是因为 Spring 的声明式事务使用了代理,具体机制此处不再探讨,但是一定要注意规避这种事务失效的场景。
- 5.3 模拟异常测试 修改下单方法,在扣减库存后抛出异常,看看事务能否回滚到修改全部未发生的状态。为了便于测试我们将库存重新设为 20 ,然后将下单方法修改如下:实例: @Transactional // 实现事务 public int createOrder(Long goodsId, Long count) { // 锁定商品库存 GoodsDo goods = goodsDao.selectForUpdate(goodsId); // 扣减库存 Long newNum = goods.getNum() - count; goods.setNum(newNum); goodsDao.update(goods); // 模拟异常 int a=1/0; // 生成订单 OrderDo order = new OrderDo(); order.setGoodsId(goodsId); order.setCount(count); int affectRows = orderDao.insert(order); return affectRows; }运行测试方法后,抛出异常,查看数据库发现,库存还是 20 ,说明 goodsDao.update(goods); 的修改没有提交到数据库,具体结果如下:模拟异常测试结果
spring事务回滚异常相关搜索
-
s line
safari浏览器
samba
SAMP
samplerate
sandbox
sanitize
saper
sas
sass
save
smarty模板
smil
smtp
snapshot
snd
snmptrap
soap
soapclient
soap协议