当前位置:首页 > 旅游指南

spring事务传播机制 Spring 事务管理

fdx 321 . github . io/2016/09/18/Spring % E4 % BA % 8B % E5 % 8A % A1 % E7 % AE % A1 % E7 % 90% 86//

1.关键类别

public interface PlatFormTransactionManager {

TransactionStatus getTransaction(

TransactionDefinition定义)引发TransactionException

voidcommit(TransactionStatus状态)引发TransactionException

voidrollback(TransactionStatus状态)引发TransactionException

}

事务的真正启动、提交和回滚是通过PlatformTransactionManager来实现的,比如我们常用的org . spring framework . JDBC . data source . data source transaction manager。

事务定义用于获取事务的一些属性,如隔离、传播、超时、只读,还定义了常数,如事务隔离级别和传播属性。

TransactionStatus用于设置和查询事务的状态,如是否是新事务、是否有保存点、RollbackOnly的设置和查询等。

2.声明性事务

声明式事务意味着通过配置节省大量代码,这样Spring就可以帮助您管理事务。本质上就是用round模式配置一个AOP,在执行方法之前用TransactionInterceptor截取,然后在事务开始之前调用一个PlatformTransactionManager的实现做一些事情,在方法执行之后再调用一个PlatformTransactionManager的实现做提交或者回滚。如图所示:

声明性事务可以通过XML、注释或两者的组合来配置。项目中通常有两种组合方式,即用XML配置数据源和事务管理器,然后通过@Transactional配置AOP(这个注解可以在类和方法上注明)。(个人认为用XML配置AOP相关配置比较繁琐,最好标注一下。)例如:

& lt!-数据源定义,使用dbcp数据源->:

& ltbean id = " DATaSOURce " class = " org . Apache . commons . dbcp . basicDATaSOURce " >的类。

& ltproperty name = " Driverclassname " value = " com . MySQL . JDBC . Driver " & gt;& lt/property>。

& ltproperty name = " URL " value = " JDBC:MySQL://localhost:3306/test " >& lt/property>。

& ltproperty name = " username " value = " root " >& lt/property>。

& ltproperty name = " password " value = " ali88 " & gt。& lt/property>。

& lt/bean>。

& lt!-事务管理器->:

& lttx:注释驱动的事务管理器= "txManager"/>。

& ltbean id = " TxManager " class = " org . spring framework . JDBC . data source . DataSourceTranctionManager " & gt;

& lt属性名称= "数据源" ref= "数据源"/>;

& lt/bean>。

& lt!- JDBC模板->:

& ltbean id = " JDBC template " class = " org . spring framework . JDBC . core . JDBC template " & gt;

& lt属性名= "数据源" >;

& ltref bean= "数据源"/>;

& lt/property>。

& lt/bean>。

@事务性(只读=真)

publicclassDefaultFooService{

public foo GetFoo(String FooName){

//做点什么

}

@Transactional(readOnly = false,传播=传播。需要_新)

publicvoidupdateFoo(Foo foo){

//做点什么

}

}

3.交易属性

引用正式文件的表格

value,在有多个事务管理器存在的情况下,用于标识使用哪个事务管理器isolation,事务的隔离级别,默认是Isolation.DEFAULT,这个DEFAULT是和具体使用的数据库相关的。关于隔离级别,可以参考MySQL事务学习总结readOnly, 是否只读,如果配置了true,但是方法里使用了update,insert语句,会报错。对于只读的事务,配置为true有助于提高性能。rollbackFor, noRollbackFor. Spring的声明式事务的默认行为是如果方法抛出RuntimeException或者Error,则事务会回滚,对于其他的checked类型的异常,不会回滚。如果想改变这种默认行为,可以通过这几个属性来配置。propagation, 后面会具体讲。

4.事务沟通机制

类型说明PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是 最常见的选择。PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行PROPAGATION_MANDATOR使用当前的事务,如果当前没有事务,就抛出异常PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作

其他的很容易理解,下面用例子介绍三种传播级别:PROGRAMME _ REQUIRED、PROGRAMME _ REQUIRED _ new和PROGRAMME _ NESTED。

表格结构和原始数据

mysql>。从测试中选择*

+ - + - +

| id |货币|

+ - + - +

| 3| 500|

| 5| 500|

| 7| 600|

+ - + - +

成套3次(0.00秒)

PROPAGATION_REQUIRED

@服务

publicclassMysqlTest01 {

@自动连线

privateJDBC template JDBC template;

@自动连线

privateMySQL test 02 MySQL test 02;

@事务性

publicvoidtest(){

JDBC Template . execute(" update test set money = ' 501 '其中id = 3 ");

尝试{

MySQL test 02 . test();

}捕获(例外e) {

System.out.println("第二次交易异常");

}

}

}

@服务

classMysqlTest02 {

@自动连线

privateJDBC template JDBC template;

@事务性(传播=传播。必需)

publicvoidtest(){

JDBC Template . execute(" update test set money = ' 502 '其中id = 3 ");

throwNewRuntimeException();

}

}

执行后,测试表的数据没有变化。

因为MysqlTest02中的事务传播类型是传播。必选,逻辑上有两个事务,但是底层共享一个物理事务,第二个事务抛出RuntimeExcetion,导致事务回滚。对于这种传播类型,内层事务的回滚将导致外层事务回滚。所以数据库中的数据没有变化。

PROPAGATION_REQUIRES_NEW

@服务

publicclassMysqlTest01 {

@自动连线

privateJDBC template JDBC template;

@自动连线

privateMySQL test 02 MySQL test 02;

@事务性

publicvoidtest(){

JDBC Template . execute(" update test set money = ' 501 '其中id = 3 ");

尝试{

MySQL test 02 . test();

}捕获(例外e) {

System.out.println("第二次交易异常");

}

}

}

@服务

classMysqlTest02 {

@自动连线

privateJDBC template JDBC template;

@事务性(传播=传播。需要_新)

publicvoidtest(){

JDBC Template . execute(" update test set money = ' 502 '其中id = 3 ");

throwNewRuntimeException();

}

}

同样的代码,唯一不同的是第二个事务的传播属性改为REQUIRES_NEW,执行结果如何?抱歉,第二笔交易无法执行。

对于REQUIRES_NEW,逻辑上有两个事务,底部有两个物理事务。由于第一个事务和第二个事务更新相同的记录,第一个事务将为Mysql的默认隔离级别REPEATABLE-READ向记录添加排他锁,因此第二个事务被卡住了。

好了,让我们把执行第二个事务的SQL语句替换为。

更新test setmoney = '501 ',其中id = 5 "

执行结果如下,可以看到只有第二个事务回滚。

mysql>。从测试中选择*

+ - + - +

| id |货币|

+ - + - +

| 5| 500|

| 3| 501|

| 7| 600|

+ - + - +

成套3次(0.00秒)

PROPAGATION_NESTED

对于这种传播类型,物理上只有一个事务,但可以有多个保存点来回滚动。当然,使用这种类型的传播需要数据库支持保存点,并且jdbc必须高于3.0版本(这并不确定)。

@服务

publicclassMysqlTest01 {

@自动连线

privateJDBC template JDBC template;

@自动连线

privateMySQL test 02 MySQL test 02;

@自动连线

privateMySQL test 03 MySQL test 03;

@事务性

publicvoidtest(){

JDBC Template . execute(" update test set money = ' 501 '其中id = 3 ");

尝试{

MySQL test 02 . test();

}捕获(例外e) {

System.out.println("第二次交易异常");

}

MySQL test 03 . test();

}

}

@服务

classMysqlTest02 {

@自动连线

privateJDBC template JDBC template;

@事务性(传播=传播。嵌套)

publicvoidtest(){

JDBC Template . execute(" update test set money = ' 502 '其中id = 3 ");

throwNewRuntimeException();

}

}

@服务

classMysqlTest03 {

@自动连线

privateJDBC template JDBC template;

@事务性(传播=传播。嵌套)

publicvoidtest(){

JDBC Template . execute(" update test set money = ' 503 '其中id = 3 ");

}

}

执行结果如下。可以看到,第一个事务和第三个事务提交成功,第二个事务回滚。物理上,它们在同一个事务中,只使用保存点技术。

mysql>。从测试中选择*

+ - + - +

| id |货币|

+ - + - +

| 5| 500|

| 3| 501|

| 7| 601|

+ - + - +

3套(0.01秒)

5.其他人

写测试代码的时候,遇到了一个关于AOP的问题。你可以看到我的测试代码,每个事务都写在一个新的类中。为什么不这样写呢?

@服务

publicclassMysqlTest01 {

@自动连线

privateJDBC template JDBC template;

@事务性

publicvoidtest01(){

JDBC Template . execute(" update test set money = ' 501 '其中id = 3 ");

test 02();

}

@事务性

publicvoidtest02(){

JDBC Template . execute(" update test set money = ' 501 '其中id = 5 ");

}

}

这是因为test01调用Spring的test02、test02 AOP,test02不会被AOP截获,所以不会被Spring管理。原因是Spring AOP的实现本质是通过动态代理执行真正的方法,然后在代理类中做一些额外的事情。通过其他类调用MysqlTest01中的test01方法时,其实是因为使用Spring的DI而注入的MysqlTest01的代理类,但通过内部方法调用test02时就不是了。

6.引文

Spring框架参考文档

1.《spring事务传播机制 Spring 事务管理》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《spring事务传播机制 Spring 事务管理》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/junshi/1178454.html

上一篇

男子微信群辱骂烈士被刑拘 对其犯罪事实供认不讳 事件详情始末介绍!

下一篇

黑化头像女 看起来特别丧的女生动漫头像!

脚崴了肿了怎么办 脚崴了,该怎么办?今天总算知道了(附康复训练方法)

  • 脚崴了肿了怎么办 脚崴了,该怎么办?今天总算知道了(附康复训练方法)
  • 脚崴了肿了怎么办 脚崴了,该怎么办?今天总算知道了(附康复训练方法)
  • 脚崴了肿了怎么办 脚崴了,该怎么办?今天总算知道了(附康复训练方法)
米仓凉子电视剧 米仓凉子决定退出奥斯卡事务所 人气日剧《Doctor-X》何去何从

米仓凉子电视剧 米仓凉子决定退出奥斯卡事务所 人气日剧《Doctor-X》何去何从

米仓凉子米仓凉子人民网东京3月26日电日本著名演艺公司奥斯卡24日宣布,其女演员米仓凉子将于3月底离职。从4月1日起,她将正式独立。 44岁的米仓凉子1992年进入奥斯卡办公室,1999年从模特转行成为演员,之后出演了《X医生》《外科医生大门未...

苹果锁屏怎么解 忘记iPhone锁屏密码?三种方法帮你顺利解决!

  • 苹果锁屏怎么解 忘记iPhone锁屏密码?三种方法帮你顺利解决!
  • 苹果锁屏怎么解 忘记iPhone锁屏密码?三种方法帮你顺利解决!
  • 苹果锁屏怎么解 忘记iPhone锁屏密码?三种方法帮你顺利解决!
写作文的方法

写作文的方法

首先建议孩子多读范文,学会模仿,才能学会创作。当然,有了素材,并不代表就能写出好文章。写作方法的指导是学生作文的拐杖。对于我们的华侨学生,我们鼓励学生模仿和学习范文。现在的孩子普遍存在以下问题:1.词汇量不足。比如写作中描述“开心”的时候,整件...

apt APT攻击常用方法与技巧

  • apt APT攻击常用方法与技巧
  • apt APT攻击常用方法与技巧
  • apt APT攻击常用方法与技巧

去除雀斑的有效方法 预防雀斑有秘诀十五种天然有效又省钱的去雀斑方法

  • 去除雀斑的有效方法 预防雀斑有秘诀十五种天然有效又省钱的去雀斑方法
  • 去除雀斑的有效方法 预防雀斑有秘诀十五种天然有效又省钱的去雀斑方法
  • 去除雀斑的有效方法 预防雀斑有秘诀十五种天然有效又省钱的去雀斑方法

median Excel的中间值函数median使用方法

  • median Excel的中间值函数median使用方法
  • median Excel的中间值函数median使用方法
  • median Excel的中间值函数median使用方法

中值 Excel的中间值函数median使用方法

  • 中值 Excel的中间值函数median使用方法
  • 中值 Excel的中间值函数median使用方法
  • 中值 Excel的中间值函数median使用方法