spring 事务说明

Spring 基础 事务说明 事务其实是一个并发控制单位,是用户定义的一个操作序列,这些操作要么全部完成,要不全部不完成,是一个不可分割的工作单位。 阅读详情
在 spring 中一共定义了六种事务传播属性, 如果你觉得看起来不够直观, 那么我来转贴一个满大街都有的翻译
引用
l          PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
l          PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
l          PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
l          PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
l          PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
l          PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
l          PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。 它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)

在我所见过的误解中, 最常见的是下面这种:
引用
假如有两个业务接口 ServiceA 和 ServiceB, 其中 ServiceA 中有一个方法实现如下
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
// 调用 ServiceB 的方法
ServiceB.methodB();
}
那么如果 ServiceB 的 methodB 如果配置了事务, 就必须配置为 PROPAGATION_NESTED
这种想法可能害了不少人, 认为 Service 之间应该避免互相调用, 其实根本不用担心这点,PROPAGATION_REQUIRED 已经说得很明白,如果当前线程中已经存在事务, 方法调用会加入此事务, 果当前没有事务,就新建一个事务, 所以 ServiceB#methodB() 的事务只要遵循最普通的规则配置为 PROPAGATION_REQUIRED 即可, 如果 ServiceB#methodB (我们称之为内部事务, 为下文打下基础) 抛了异常, 那么 ServiceA#methodA(我们称之为外部事务) 如果没有特殊配置此异常时事务提交 (即 +MyCheckedException的用法), 那么整个事务是一定要 rollback 的, 什么 Service 只能调 Dao 之类的言论纯属无稽之谈, spring 只负责配置了事务属性方法的拦截, 它怎么知道你这个方法是在 Service 还是 Dao 里 ?


也就是说, 最容易弄混淆的其实是 PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED, 那么这两种方式又有何区别呢? 我简单的翻译一下 Juergen Hoeller 的话 :
PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 committed 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.
另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务, 它是已经存在事务的一个真正的子事务. 嵌套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.
由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 嵌套事务也会被 commit, 这个规则同样适用于 roll back.
那么外部事务如何利用嵌套事务的 savepoint 特性呢, 我们用代码来说话
代码
ServiceA {
    /**  
     * 事务属性配置为 PROPAGATION_REQUIRED  
     */  
    void methodA() {   
        ServiceB.methodB();   
    }   
}   
  
ServiceB {
    /**  
     * 事务属性配置为 PROPAGATION_REQUIRES_NEW  
     */    
    void methodB() {   
    }  
}      
这种情况下, 因为 ServiceB#methodB 的事务属性为 PROPAGATION_REQUIRES_NEW, 所以两者不会发生任何关系, ServiceA#methodA 和 ServiceB#methodB 不会因为对方的执行情况而影响事务的结果, 因为它们根本就是两个事务, 在 ServiceB#methodB 执行时 ServiceA#methodA 的事务已经挂起了 (关于事务挂起的内容已经超出了本文的讨论范围, 有时间我会再写一些挂起的文章) .
那么 PROPAGATION_NESTED 又是怎么回事呢? 继续看代码
代码
ServiceA {
    /**  
     * 事务属性配置为 PROPAGATION_REQUIRED  
     */  
    void methodA() {   
        ServiceB.methodB();   
    }  
}   
  
ServiceB {
    /**  
     * 事务属性配置为 PROPAGATION_NESTED  
     */    
    void methodB() {   
    }   
}      
现在的情况就变得比较复杂了, ServiceB#methodB 的事务属性被配置为 PROPAGATION_NESTED, 此时两者之间又将如何协作呢? 从 Juergen Hoeller 的原话中我们可以找到答案, ServiceB#methodB 如果 rollback, 那么内部事务(即 ServiceB#methodB) 将回滚到它执行前的 SavePoint(注意, 这是本文中第一次提到它, 嵌套事务中最核心的概念), 而外部事务(即 ServiceA#methodA) 可以有以下两种处理方式:
1. 改写 ServiceA 如下
代码
ServiceA {   
       
    /**  
     * 事务属性配置为 PROPAGATION_REQUIRED  
     */  
    void methodA() {   
        try {   
            ServiceB.methodB();   
        } catch (SomeException) {   
            // 执行其他业务, 如 ServiceC.methodC();   
        }   
    }   
  
}   
  
这种方式也是嵌套事务最有价值的地方, 它起到了分支执行的效果, 如果 ServiceB.methodB 失败, 那么执行 ServiceC.methodC(), 而 ServiceB.methodB 已经回滚到它执行之前的 SavePoint, 所以不会产生脏数据(相当于此方法从未执行过), 这种特性可以用在某些特殊的业务中, 而 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRES_NEW 都没有办法做到这一点. (题外话 : 看到这种代码, 似乎似曾相识, 想起了 prototype.js 中的 Try 函数 )
2. 代码不做任何修改, 那么如果内部事务(即 ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前的 SavePoint(在任何情况下都会如此), 外部事务(即 ServiceA#methodA) 将根据具体的配置决定自己是 commit 还是 rollback (+MyCheckedException).
上面大致讲述了嵌套事务的使用场景, 下面我们来看如何在 spring 中使用 PROPAGATION_NESTED, 首先来看AbstractPlatformTransactionManager
代码
/**  
 * Create a TransactionStatus for an existing transaction.  
 */  
private TransactionStatus handleExistingTransaction(   
        TransactionDefinition definition, Object transaction, boolean debugEnabled)   
        throws TransactionException {   
  
   ... 省略   
  
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {   
        if (!isNestedTransactionAllowed()) {   
            throw new NestedTransactionNotSupportedException(   
                    "Transaction manager does not allow nested transactions by default - " +   
                    "specify 'nestedTransactionAllowed' property with value 'true'");   
        }   
        if (debugEnabled) {   
            logger.debug("Creating nested transaction with name [" + definition.getName() + "]");   
        }   
        if (useSavepointForNestedTransaction()) {   
            // Create savepoint within existing Spring-managed transaction,   
            // through the SavepointManager API implemented by TransactionStatus.   
            // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.   
            DefaultTransactionStatus status =   
                    newTransactionStatus(definition, transaction, false, false, debugEnabled, null);   
            status.createAndHoldSavepoint();   
            return status;   
        }   
        else {   
            // nested transaction through nested begin and commit/rollback calls.   
            // Usually only for JTA: Spring synchronization might get activated here   
            // in case of a pre-existing JTA transaction.   
            doBegin(transaction, definition);   
            boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);   
            return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);   
        }   
    }   
}   
 
一目了然
1. 我们要设置 transactionManager 的 nestedTransactionAllowed 属性为 true, 注意, 此属性默认为 false!!!再看 AbstractTransactionStatus#createAndHoldSavepoint() 方法
代码
/**  
 * Create a savepoint and hold it for the transaction.  
 * @throws org.springframework.transaction.NestedTransactionNotSupportedException  
 * if the underlying transaction does not support savepoints  
 */  
public void createAndHoldSavepoint() throws TransactionException {   
    setSavepoint(getSavepointManager().createSavepoint());   
}   
可以看到 Savepoint 是 SavepointManager.createSavepoint 实现的, 再看 SavepointManager 的层次结构, 发现其 Template 实现是 JdbcTransactionObjectSupport, 常用的 DatasourceTransactionManager, HibernateTransactionManager 中的 TransactonObject 都是它的子类 :
 
1.      JdbcTransactionObjectSupport 告诉我们必须要满足两个条件才能 createSavepoint :
2.      java.sql.Savepoint 必须存在, 即 jdk 版本要 1.4+
3.      Connection.getMetaData().supportsSavepoints() 必须为 true, 即 jdbc drive 必须支持 JDBC 3.0
确保以上条件都满足后, 你就可以尝试使用 PROPAGATION_NESTED 了. (全文完)

spring事务管理 spring事务管理 配置文件等详解 立即下载

相关推荐

Unity 开发Apple Vision Pro物体识别追踪ObjectTracking

当您在 visionOS 应用中实现对象跟踪时,您可以将现实世界中的物体无缝集成到人们的周围环境中,以增强他们的沉浸式体验。通过跟踪一个或多个物体的 3D 位置和方向,您的应用可以使用虚拟内容增强它们。您可以使用对象跟踪来提供与人周围环境中的对象的虚拟交互,例如:引导某人使用某件物品的功能、阅读其历史或了解其在周围环境中的行为。使用虚拟手册帮助人们解决家居用品和电器的问题。

Cool-浩 1185

Spring 事务保存点savepoint

Savepoint savepoint=null;保存点,记录操作位置,之后可以回滚到指定位置 try{ //获得链接 conn=。。。。 //开启事务 conn.setAutoCommit(false); A事务B事务 savepoint=conn.setpoint(); C事务 D事务 //提交事务 conn.commit(); ...

weixin_30882895的博客 1367

Tushare Day2——了解stock_basic数据并根据行业和地区进行统计

了解stock_basic数据 1  stock_basic基础信息2  导入包和stock_basic数据、查看基本信息3  根据行业列进行统计3.1  1.先把不同行业列举出来,看一下一共有多少种行业3.2  2.统计每个行业分别有多少家公司3.3  3.把行业从array的二维数组形式变成list形式3.4  4.把行业从list形式转换成文本形式3.5&nbsp

绒绒的Routine 2796

Spring-tx-TransactionStatus接口(savepoint)

怀念二抱三抱

文天大人 2872

Wiley:International Journal for Numerical Methods in Biomedical Engineering投稿流程

中间过程省略,这个出版社很人性化,投稿的web UI也很好看。上传word之后,一步步跟着走就行,不用填太多东西。不要最后在最后检查阶段,重新上传word文件,这样会导致,之前针对word的操作全部改变。

Everyday try to become better -Kobe Bryant 2545

STM32驱动WS2812B实现音乐频谱可视化系统

本文详细介绍了基于STM32驱动WS2812B灯带实现音乐频谱可视化系统的设计与实现。通过FFT算法实时分析音频信号,将频谱映射到炫彩灯光控制系统,结合PWM和DMA技术实现低延迟响应。系统支持多模式切换和动态亮度调节,适用于创意灯光秀和智能家居场景。

weixin_29171129的博客 302

Spring 事务设置回滚点 savepoint

@Transactional public void method1() { String sql = "insert into names values('1')"; jdbcTemplate.update(sql); DefaultTransactionStatus transactionStatus = (DefaultTrans...

weixin_42678334的博客 3458

ArcGIS Pro 制作这种地图海报

ArcMap 版本与 ArcGIS Pro 版本的制图功能相差太多,无论从美观上还是制图效率都远远优于 ArcMap,用了一段时间的 ArcGIS Pro ,真心推荐有条件的大家赶紧试一试!一个软件也能搞定一张不错的海报哦!----吐槽:好的设计真的是门花时间的活,这个教程大概花了我7小时左右,我都忘了我自己教程中截图多少张了!(可能是我速度太慢了)测试数据:阿里云盘分享-----北极海冰数据.https://www.aliyundrive.com/s/SUhsnqfkmXh。

J_Giser的博客 1427

Spring 事务控制

文章目录spring事务控制简介 spring事务控制 简介 事务是恢复和并发控制的基本单位。 事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的

qq_18478183的博客 1474

TC397 EB MCAL开发从0开始系列 之 [15.1] Fee配置实战 - 双扇区demo

TC397 EB MCAL Fee模块实战之双扇区配置使用

yy九歌的博客 1127

【银河麒麟V10】【桌面】【服务器】系统启动问题

1、如果之前运行好好的,重启后系统报错,一般80%是因为fstab的问题,回想下之前有没有添加过外接存储,修改过/etc/fstab,如果是的话一般是因为存储异常(比如网络存储无法连接,本地存储路径变化)导致系统开机自检失败,导致无法正常启动; 处理方式:进入单用户(单用户进入的几种方式上面有专门文章介绍),修改/etc/fstab,将新增的内容暂时注释掉,然后重启系统,能正常进入系统后再分析失败原因。 ...

桂安俊@KylinOS 3万+

Spring 事务(详解)

将⼀组操作封装成⼀个执⾏单元,要么全部成功要么全部失败。

qq_45559559的博客 1万+

YOLOv8性能突破:DySample超轻量动态上采样算子的创新应用与实现【附保姆级代码】

YOLOv8(You Only Look Once Version 8)作为YOLO系列模型的最新版本,延续了高效、准确的目标检测优势。其基础结构包含了骨干网络(Backbone)、检测头(Head)、以及特征融合层(Neck)。在特征融合阶段,YOLOv8需要对不同尺度的特征图进行上采样,以便将低分辨率的特征与高分辨率的特征进行融合。传统的上采样操作多使用插值(如双线性插值)或固定卷积,而这些方法可能无法很好地适应复杂的上下文信息。

一键难忘的博客 3120

Spring 对于事务上的应用的详细说明

什么是事务在一个业务流程当中,通常需要多条DML(insert delete update) 语句共同联合才能完成,这多条DML语句必须同时成功,或者同时失败,这样才能保证数据的安全。多条DML要么同时成功,要么同时失败,这叫做事务。事务(Transaction)第一步:开启事务(start transaction)第二步:执行核心业务代码第三步:提交事务(如果核心业务处理过程中没有出现异常)(commit transaction)

2501_92608043的博客 975

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Spring AOP及事务说明

事务的传播行为我们只需要掌握两个:REQUIRED、REQUIRES_NEW。REQUIRED :大部分情况下都是用该传播行为即可。REQUIRES_NEW :当我们不希望事务之间相互影响时,可以使用该传播行为。比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。什么是AOP?* AOP英文全称:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。

m0_72167535的博客 1716

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring中的事务简介说明

Spring中的事务简介说明

qq_25073223的博客 250

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

spring的两种常用事务传播属性说明

常用的两种传播属性: 1.REQUIRED 如果存在当前事务则用当前事务,如果不存在当前事务,则新建一个事务 2.REQUIRES_NEW 如果当前存在事务则挂起当前事务,开启一个新事务,新事务执行完毕后,唤醒之前挂起的事务,继续执行。如果不存在当前事务,则新建一个事务 第一种情况: 执行controller以后事务会回滚,两条数都插不进去。(propagation如果不写默认的是...

qianxiaopeng的专栏 1万+

Spring事务说明与自实现

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33809981的博客 90

Spring事务说明

最近有朋友问到spring中事务的配置,以下就是比较常见的配置   配置文件如下:<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans "xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance ...

130

spring mvc 事务配置,spring 事务配置说明

新建项目记录下springmvc和spring的事务配置,解决事务不回滚的问题。 问题说明: Spring容器优先加载由ServletContextListener(applicationContext.xml)产生的父容器,而SpringMVC(spring-mvc.xm...

chijunmei7041的博客 172
上一篇: phoenix 3.1 + hbase 0.94.21 的安装和使用
下一篇: hbase shell&java 获取多版本的值
wind520
博客等级 码龄25年 303粉丝 264原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值