苏州网站建设找哪家,小程序电商平台需要什么资质,建筑网架结构图片,东莞建设工程交易中心门户网站Spring事务传播机制 1.什么是事务传播机制#xff1f;2.Spring事务传播类型Propagation介绍3.具体案例总结
Spring事务传播机制 1.什么是事务传播机制#xff1f; 举个栗子#xff0c;方法A是一个事务的方法#xff0c;方法A执行过程中调用了方法B#xff0c;那么方法B有…Spring事务传播机制 1.什么是事务传播机制2.Spring事务传播类型Propagation介绍3.具体案例总结
Spring事务传播机制 1.什么是事务传播机制 举个栗子方法A是一个事务的方法方法A执行过程中调用了方法B那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务具体执行造成影响同时方法A的事务对方法B的事务执行也有影响这种影响具体是什么就由两个方法所定义的事务传播类型所决定。 简单说就是我们方法调用通常是一个方法调用另外一个而不同方法可以有不同的事务所以传播机制就是指在多个方法事务要如何传播。 2.Spring事务传播类型Propagation介绍
一共有七种传播类型
Propagation.REQUIREDPropagation.SUPPORTSPropagation.MANDATORYPropagation.REQUIRED_NEWPropagation.NOT_SUPPORTEDPropagation.NESTEDPropagation.NEVER
本文从案例结合解释一下不同传播类型下多个Transactional方法会发生什么在遇到异常情况下不同传播机制会产生什么影响。
1. Propagation.REQUIRED
这是默认的传播机制我们最常用的一种也是Transactional默认的一种 如果当前没有事务则自己新建一个事务如果当前存在事务则加入这个事务 1 2 3 4 5 6 7 8 9 10 11 12 // 示例1 Transactional(propagation Propagation.REQUIRED) public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.REQUIRED) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
简单来说就是开启一个事务上面的案例就是当main方法如果没开启事务那么sub方法就会开启如果main方法已经Transactional开启了事务sub方法就会加入外层方法的事务所以上面方法执行在遇到异常时候会全部回滚
结果
A、B、C全部无法插入。 1 2 3 4 5 6 7 8 9 10 11 // 示例2 public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.REQUIRED) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
结果
A插入成功BC开启新的事务遇到异常回滚B、C无法插入
2. Propagation.SUPPORTS 当前存在事务则加入当前事务如果当前没有事务就以非事务方法执行 1 2 3 4 5 6 7 8 9 10 11 // 示例3 public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.SUPPORTS) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
这个和REQUIRED很像但是里层的sub方法事务取决于main方法如果main方法有开启那么里面的就和外层事务一起如果发生异常全部回滚。
结果
A、B插入成功C无法插入因为发生异常
3. Propagation.MANDATORY 当前存在事务则加入当前事务如果当前事务不存在则抛出异常。 1 2 3 4 5 6 7 8 9 10 11 // 示例4 public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.MANDATORY) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
这种情形的执行结果就是insertA存储成功而insertB和insertC没有存储。b和c没有存储并不是事务回滚的原因而是因为main方法没有声明事务在去执行sub方法时就直接抛出事务要求的异常如果当前事务不存在则抛出异常所以sub方法里的内容就完全没有执行。
结果
A插入成功B、C无法插入方法抛出异常
那么当main方法有事务的情况下 1 2 3 4 5 6 7 8 9 10 11 12 // 示例5 Transactional(propagation Propagation.REQUIRED) public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.MANDATORY) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
结果
A、B、C全部无法插入A、B回滚
4. Propagation.REQUIRED_NEW 创建一个新事务如果存在当前事务则挂起该事务。 1 2 3 4 5 6 7 8 9 10 11 12 // 示例5 Transactional(propagation Propagation.REQUIRED) public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 throw RuntimeException; //发生异常抛出 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.REQUIRES_NEW) public void sub(){ insertB(); //插入B insertC(); //调用C
因为sub方法会开启一个新的事务所以main方法抛出的异常并不会影响sub方法的提交
结果
A插入失败B、C能插入成功
5. Propagation.NOT_SUPPORTED 始终以非事务方式执行,如果当前存在事务则挂起当前事务 1 2 3 4 5 6 7 8 9 10 11 12 // 示例6 Transactional(propagation Propagation.REQUIRED) public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.NOT_SUPPORTED) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
示例6因为当main方法有事务的时候就会挂起当前事务即main以事务运行sub不以事务运行
所以最终结果
A因为sub抛出异常事务回滚插入失败B因为不以事务运行插入成功C因为遇到异常后续不会执行所以插入失败。 1 2 3 4 5 6 7 8 9 10 11 // 示例7 public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.NOT_SUPPORTED) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
示例7这种情况就是所有方法都不会以事务运行A、B均能插入成功C无法插入
6. Propagation.NEVER 不使用事务如果当前事务存在则抛出异常 1 2 3 4 5 6 7 8 9 10 11 // 示例7 Transactional(propagation Propagation.REQUIRED) public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.NEVER) public void sub(){ insertB(); //插入B insertC(); //调用C
sub因为是Never所以是不会执行直接抛出错误所以main的事务遇到异常直接回滚所以A回滚无法插入B、C不会插入。
7. Propagation.NESTED 如果当前事务存在则在嵌套父子事务中执行否则REQUIRED的操作一样开启一个事务 1 2 3 4 5 6 7 8 9 10 11 12 // 示例7 Transactional(propagation Propagation.REQUIRED) public void main(){ insertA(); // 插入A service.sub(); // 调用其他方法 throw RuntimeException; //发生异常抛出 } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.NESTED) public void sub(){ insertB(); //插入B insertC(); //调用C
这个是最需要理解的一种传播机制要理清楚嵌套父子事务main的是父事务sub是子事务main发生异常全部都会回滚。
结果
A、B、C全部回滚 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 示例8 Transactional(propagation Propagation.REQUIRED) public void main(){ insertA(); // 插入A try { service.sub(); // 调用其他方法 } catch (Exception e) { } insertD(); } // 两个Service中调用如果同一个要注意不能用this调用事务不会起作用 Transactional(propagation Propagation.NESTED) public void sub(){ insertB(); //插入B throw RuntimeException; //发生异常抛出 insertC(); //调用C
示例8子事务发生异常抛出但父事务catch掉了那么这个时候main方法就相当于正常执行没有发生异常那么就只有子事务回滚。
结果
A、D插入成功B、C插入失败
REQUIRED 内外同一个事务任何一个地方抛出异常全部一起回滚。REQUIRED_NEW 内部开启一个新的事务外部事务回滚并不会影响内部的事务而如果内部事务抛出被catch也不会影响外部事务。
怎么样快速记忆七个分四组221这样记两个一对互相类似
组传播类型含义group1Propagation.REQUIRED如果当前已有事务则加入当前事务否则开启新的事务group1Propagation.REQUIRED_NEW无论当前是否有事务都开启新的事务group2Propagation.SUPPORTED如果当前事务存在就加入事务否则以非事务运行group2Propagation.NOT_SUPPORTED始终以非事务方式执行,如果当前存在事务则挂起当前事务group3Propagation.NEVER不使用事务如果当前事务存在则抛出异常group3Propagation.MANDATORY当前存在事务则加入当前事务如果当前事务不存在则抛出异常。group4Propagation.NESTED父子嵌套事务父回滚全回滚子回滚不影响父事务 3.具体案例
单纯讲案例比较枯燥会觉得工作中什么情况会使用到呢这边就举一个例子来讲解一下。 在下单时候我们最主要是写入订单、然后添加积分最后记录日志 1 2 3 4 5 6 7 8 9 10 11 12 13 Service public class OrderServiceImpl implements OrderService{ Transactional public void placeOrder(OrderDTO orderDTO){ try { pointService.addPoint(Point point); } catch (Exception e) { // 记录错误信息 } //省略... } //省略... } 1 2 3 4 5 6 7 8 9 10 11 12 13 Service public class PointServiceImpl implements PointService{ Transactional(propagation Propagation.NESTED) public void addPoint(Point point){ try { recordService.addRecord(Record record); } catch (Exception e) { //省略... } //省略... } //省略... } 1 2 3 4 5 6 7 8 Service public class RecordServiceImpl implements RecordService{ Transactional(propagation Propagation.NOT_SUPPORTED) public void addRecord(Record record){ //省略... } //省略... }
下单的操作不会影响添加积分的操作所以我们使用NESTED下单只要成功添加积分可以成功或失败失败的话就错误信息后续补偿。而记录日志我们可以有也可以没有就可以设置为NOT_SUPPORTED不开启事务使得事务的方法能尽可能的精简避免一个很大的事务方法。 总结
本文讲解了Spring事务的七种传播机制我们可以根据具体的类型具体设置避免事务的方法过于长一个事务里面调用的库表越多就越有可能造成死锁所以我们要根据具体的需要拆分使用。