- 浏览: 1526129 次
- 性别:
- 来自: 厦门
博客专栏
-
Spring 3.x企业实...
浏览量:463890
文章分类
最新评论
-
JyeChou:
学习Spring必学的Java基础知识(1)----反射 -
hhzhaoheng:
...
《Spring4.x企业应用开发实战》光盘资料下载 -
renlongnian:
//assertReflectionEquals(user1, ...
单元测试系列之3:测试整合之王Unitils -
骑着蜗牛超F1:
huang_yong 写道我的经验是,只需定义三层:1.ent ...
Spring的事务管理难点剖析(2):应用分层的迷惑 -
wangyudong:
工具地址貌似更新了哦https://github.com/Wi ...
几种常用的REST webservice客户端测试工具
Spring事务传播机制回顾
Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务。结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷。
其实这是不认识Spring事务传播机制而造成的误解,Spring对事务控制的支持统一在TransactionDefinition类中描述,该类有以下几个重要的接口方法:
很明显,除了事务的传播行为外,事务的其他特性Spring是借助底层资源的功能来完成的,Spring无非只充当个代理的角色。但是事务的传播行为却是Spring凭借自身的框架提供的功能,是Spring提供给开发者最珍贵的礼物,讹传的说法玷污了Spring事务框架最美丽的光环。
所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。Spring支持以下7种事务传播行为。
Spring默认的事务传播行为是PROPAGATION_REQUIRED,它适合绝大多数的情况,如果多个ServiveX#methodX()均工作在事务环境下(即均被Spring事务增强),且程序中存在如下的调用链:Service1#method1()->Service2#method2()->Service3#method3(),那么这3个服务类的3个方法通过Spring的事务传播机制都工作在同一个事务中。
相互嵌套的服务方法
我们来看一下实例,UserService#logon()方法内部调用了UserService#updateLastLogon Time()和ScoreService#addScore()方法,这两个类都继承于BaseService。它们之间的类结构如下图所示:
UserService#logon()方法内部调用了ScoreService#addScore()的方法,两者都分别通过Spring AOP进行了事务增强,则它们工作于同一事务中。来看具体的代码:
UserService中注入了ScoreService的Bean,而ScoreService的代码如下所示:
通过Spring配置为ScoreService及UserService中所有公有方法都添加Spring AOP的事务增强,让UserService的logon()和updateLastLogonTime()及ScoreService的addScore()方法都工作于事务环境下。下面是关键的配置代码:
将日志级别设置为DEBUG,启动Spring容器并执行UserService#logon()的方法,仔细观察如下输出日志:
从上面的输出日志中,可以清楚地看到Spring为UserService#logon()方法启动了一个新的事务,而UserSerive#updateLastLogonTime()和UserService#logon()是在相同的类中,没有观察到有事务传播行为的发生,其代码块好像“直接合并”到UserService#logon()中。
然而在执行到ScoreService#addScore()方法时,我们就观察到发生一个事务传播的行为:" Participating in existing transaction ",这说明ScoreService#addScore()添加到UserService#logon()的事务上下文中,两者共享同一个事务。所以最终的结果是UserService的logon()、updateLastLogonTime()以及ScoreService的addScore都工作于同一事务中。
注:以上内容摘自《Spring 4.x企业应用开发实战》
版本一样嘛? 结果如果正确 这个不用纠结
晕 还以为我博客那 哈哈哈
版本一样嘛? 结果如果正确 这个不用纠结
可以参考 我的这篇帖子 http://www.iteye.com/topic/1121357
你的需求是 RequiresNew
为什么是RequiresNew呢?明明是嵌套事务
具体 可以看我画的几个传播行为的图,地址:
http://jinnianshilongnian.iteye.com/blog/1441271
你的需求是 RequiresNew
为什么是RequiresNew呢?明明是嵌套事务
c
a
b
当b失败时a成功,对不?
因此RequiresNew也是可以的。
当然也可以用Nested传播行为实现。
如图
你的需求是 RequiresNew
为什么是RequiresNew呢?明明是嵌套事务
你的需求是 RequiresNew
Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务。结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷。
其实这是不认识Spring事务传播机制而造成的误解,Spring对事务控制的支持统一在TransactionDefinition类中描述,该类有以下几个重要的接口方法:
- int getPropagationBehavior():事务的传播行为
- int getIsolationLevel():事务的隔离级别
- int getTimeout():事务的过期时间
- boolean isReadOnly():事务的读写特性
很明显,除了事务的传播行为外,事务的其他特性Spring是借助底层资源的功能来完成的,Spring无非只充当个代理的角色。但是事务的传播行为却是Spring凭借自身的框架提供的功能,是Spring提供给开发者最珍贵的礼物,讹传的说法玷污了Spring事务框架最美丽的光环。
所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。Spring支持以下7种事务传播行为。
- PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,就加入到这个事务中。这是最常见的选择。
- PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
Spring默认的事务传播行为是PROPAGATION_REQUIRED,它适合绝大多数的情况,如果多个ServiveX#methodX()均工作在事务环境下(即均被Spring事务增强),且程序中存在如下的调用链:Service1#method1()->Service2#method2()->Service3#method3(),那么这3个服务类的3个方法通过Spring的事务传播机制都工作在同一个事务中。
相互嵌套的服务方法
我们来看一下实例,UserService#logon()方法内部调用了UserService#updateLastLogon Time()和ScoreService#addScore()方法,这两个类都继承于BaseService。它们之间的类结构如下图所示:
UserService#logon()方法内部调用了ScoreService#addScore()的方法,两者都分别通过Spring AOP进行了事务增强,则它们工作于同一事务中。来看具体的代码:
package com.baobaotao.nestcall; … @Service("userService") public class UserService extends BaseService { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private ScoreService scoreService; //①该方法嵌套调用了本类的其他方法及其他服务类的方法 public void logon(String userName) { System.out.println("before userService.updateLastLogonTime..."); updateLastLogonTime(userName);//①-1本服务类的其他方法 System.out.println("after userService.updateLastLogonTime..."); System.out.println("before scoreService.addScore..."); scoreService.addScore(userName, 20); //①-2其他服务类的其他方法 System.out.println("after scoreService.addScore..."); } public void updateLastLogonTime(String userName) { String sql = "UPDATE t_user u SET u.last_logon_time = ? WHERE user_name =?"; jdbcTemplate.update(sql, System.currentTimeMillis(), userName); }
UserService中注入了ScoreService的Bean,而ScoreService的代码如下所示:
package com.baobaotao.nestcall; … @Service("scoreUserService") public class ScoreService extends BaseService{ @Autowired private JdbcTemplate jdbcTemplate; public void addScore(String userName, int toAdd) { String sql = "UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?"; jdbcTemplate.update(sql, toAdd, userName); } }
通过Spring配置为ScoreService及UserService中所有公有方法都添加Spring AOP的事务增强,让UserService的logon()和updateLastLogonTime()及ScoreService的addScore()方法都工作于事务环境下。下面是关键的配置代码:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <context:component-scan base-package="com.baobaotao.nestcall"/> … <bean id="jdbcManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/> <!--①通过以下配置为所有继承BaseService类的所有子类的所有public方法都添加事务增强--> <aop:config proxy-target-class="true"> <aop:pointcut id="serviceJdbcMethod" expression="within(com.baobaotao.nestcall.BaseService+)"/> <aop:advisor pointcut-ref="serviceJdbcMethod" advice-ref="jdbcAdvice" order="0"/> </aop:config> <tx:advice id="jdbcAdvice" transaction-manager="jdbcManager"> <tx:attributes> <tx:method name="*"/> </tx:attributes> </tx:advice> </beans>
将日志级别设置为DEBUG,启动Spring容器并执行UserService#logon()的方法,仔细观察如下输出日志:
引用
before userService.logon method...
//①创建了一个事务
Creating new transaction with name [com.baobaotao.nestcall.UserService.logon]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction
Switching JDBC Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit
before userService.updateLastLogonTime...
<!--②updateLastLogonTime()和logon()在同一个Bean中,并未发生加入已存在事务上下文的
动作,而是“天然”地工作于相同的事务上下文-->
Executing prepared SQL update
Executing prepared SQL statement [UPDATE t_user u SET u.last_logon_time = ? WHERE user_name =?]
SQL update affected 1 rows
after userService.updateLastLogonTime...
before scoreService.addScore...
//③ScoreService#addScore方法加入到①处启动的事务上下文中
Participating in existing transaction
Executing prepared SQL update
Executing prepared SQL statement [UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?]
SQL update affected 1 rows
after scoreService.addScore...
Initiating transaction commit
Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver]
…
after userService.logon method...
//①创建了一个事务
Creating new transaction with name [com.baobaotao.nestcall.UserService.logon]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver] for JDBC transaction
Switching JDBC Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver] to manual commit
before userService.updateLastLogonTime...
<!--②updateLastLogonTime()和logon()在同一个Bean中,并未发生加入已存在事务上下文的
动作,而是“天然”地工作于相同的事务上下文-->
Executing prepared SQL update
Executing prepared SQL statement [UPDATE t_user u SET u.last_logon_time = ? WHERE user_name =?]
SQL update affected 1 rows
after userService.updateLastLogonTime...
before scoreService.addScore...
//③ScoreService#addScore方法加入到①处启动的事务上下文中
Participating in existing transaction
Executing prepared SQL update
Executing prepared SQL statement [UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?]
SQL update affected 1 rows
after scoreService.addScore...
Initiating transaction commit
Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver]
…
after userService.logon method...
从上面的输出日志中,可以清楚地看到Spring为UserService#logon()方法启动了一个新的事务,而UserSerive#updateLastLogonTime()和UserService#logon()是在相同的类中,没有观察到有事务传播行为的发生,其代码块好像“直接合并”到UserService#logon()中。
然而在执行到ScoreService#addScore()方法时,我们就观察到发生一个事务传播的行为:" Participating in existing transaction ",这说明ScoreService#addScore()添加到UserService#logon()的事务上下文中,两者共享同一个事务。所以最终的结果是UserService的logon()、updateLastLogonTime()以及ScoreService的addScore都工作于同一事务中。
注:以上内容摘自《Spring 4.x企业应用开发实战》
评论
12 楼
jinnianshilongnian
2012-06-11
jinnianshilongnian 写道
janwen 写道
janwen 写道
有些log4j日志我看到怎么跟博客里的输出不一样啊.是什么配置不对吗?
[DEBUG] 2012-06-11 13:36:49,417 [main] transaction.interceptor.NameMatchTransactionAttributeSource (NameMatchTransactionAttributeSource.java:94) -Adding transactional method [*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT] [DEBUG] 2012-06-11 13:37:08,490 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:08,495 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [INSERT INTO stuff SET name=?,age=?] [DEBUG] 2012-06-11 13:37:08,536 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows [DEBUG] 2012-06-11 13:37:20,050 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:20,052 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [UPDATE stuff sf SET sf.name=?,sf.age=? WHERE sf.name=?] [DEBUG] 2012-06-11 13:37:20,062 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows
版本一样嘛? 结果如果正确 这个不用纠结
晕 还以为我博客那 哈哈哈
11 楼
jinnianshilongnian
2012-06-11
janwen 写道
janwen 写道
有些log4j日志我看到怎么跟博客里的输出不一样啊.是什么配置不对吗?
[DEBUG] 2012-06-11 13:36:49,417 [main] transaction.interceptor.NameMatchTransactionAttributeSource (NameMatchTransactionAttributeSource.java:94) -Adding transactional method [*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT] [DEBUG] 2012-06-11 13:37:08,490 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:08,495 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [INSERT INTO stuff SET name=?,age=?] [DEBUG] 2012-06-11 13:37:08,536 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows [DEBUG] 2012-06-11 13:37:20,050 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:20,052 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [UPDATE stuff sf SET sf.name=?,sf.age=? WHERE sf.name=?] [DEBUG] 2012-06-11 13:37:20,062 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows
版本一样嘛? 结果如果正确 这个不用纠结
10 楼
janwen
2012-06-11
janwen 写道
有些log4j日志我看到怎么跟博客里的输出不一样啊.是什么配置不对吗?
[DEBUG] 2012-06-11 13:36:49,417 [main] transaction.interceptor.NameMatchTransactionAttributeSource (NameMatchTransactionAttributeSource.java:94) -Adding transactional method [*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT] [DEBUG] 2012-06-11 13:37:08,490 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:08,495 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [INSERT INTO stuff SET name=?,age=?] [DEBUG] 2012-06-11 13:37:08,536 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows [DEBUG] 2012-06-11 13:37:20,050 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:20,052 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [UPDATE stuff sf SET sf.name=?,sf.age=? WHERE sf.name=?] [DEBUG] 2012-06-11 13:37:20,062 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows
9 楼
janwen
2012-06-11
有些log4j日志我看到怎么跟博客里的输出不一样啊.是什么配置不对吗?
[DEBUG] 2012-06-11 13:36:49,417 [main] transaction.interceptor.NameMatchTransactionAttributeSource (NameMatchTransactionAttributeSource.java:94) -Adding transactional method [*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT] [DEBUG] 2012-06-11 13:37:08,490 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:08,495 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [INSERT INTO stuff SET name=?,age=?] [DEBUG] 2012-06-11 13:37:08,536 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows [DEBUG] 2012-06-11 13:37:20,050 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:811) -Executing prepared SQL update [DEBUG] 2012-06-11 13:37:20,052 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:570) -Executing prepared SQL statement [UPDATE stuff sf SET sf.name=?,sf.age=? WHERE sf.name=?] [DEBUG] 2012-06-11 13:37:20,062 [main] jdbc.core.JdbcTemplate (JdbcTemplate.java:820) -SQL update affected 1 rows
8 楼
jinnianshilongnian
2012-04-15
huang_yong 写道
补充:
如何在代码中使用@Transactional注解及其属性,最好也能说明一下。
如何在代码中使用@Transactional注解及其属性,最好也能说明一下。
可以参考 我的这篇帖子 http://www.iteye.com/topic/1121357
7 楼
huang_yong
2012-04-14
补充:
如何在代码中使用@Transactional注解及其属性,最好也能说明一下。
如何在代码中使用@Transactional注解及其属性,最好也能说明一下。
6 楼
huang_yong
2012-04-14
建议作者,关于其它传播机制也需要补充一下吧。
关于“隔离级别”也是否需要补充一下呢?
谢谢!
关于“隔离级别”也是否需要补充一下呢?
谢谢!
5 楼
jinnianshilongnian
2012-03-10
OracleX 写道
jinnianshilongnian 写道
OracleX 写道
正常情况下没有问题,如果其中一个事务出现异常,另一个正常执行需要怎么处理
你的需求是 RequiresNew
为什么是RequiresNew呢?明明是嵌套事务
具体 可以看我画的几个传播行为的图,地址:
http://jinnianshilongnian.iteye.com/blog/1441271
4 楼
jinnianshilongnian
2012-03-10
OracleX 写道
jinnianshilongnian 写道
OracleX 写道
正常情况下没有问题,如果其中一个事务出现异常,另一个正常执行需要怎么处理
你的需求是 RequiresNew
为什么是RequiresNew呢?明明是嵌套事务
c
a
b
当b失败时a成功,对不?
因此RequiresNew也是可以的。
当然也可以用Nested传播行为实现。
如图
3 楼
OracleX
2012-03-10
jinnianshilongnian 写道
OracleX 写道
正常情况下没有问题,如果其中一个事务出现异常,另一个正常执行需要怎么处理
你的需求是 RequiresNew
为什么是RequiresNew呢?明明是嵌套事务
2 楼
jinnianshilongnian
2012-03-09
OracleX 写道
正常情况下没有问题,如果其中一个事务出现异常,另一个正常执行需要怎么处理
你的需求是 RequiresNew
1 楼
OracleX
2012-03-09
正常情况下没有问题,如果其中一个事务出现异常,另一个正常执行需要怎么处理
发表评论
-
一个常见的Spring IOC疑难症状
2013-07-25 14:14 5039Case 请看下面的IOC实例: 1)Aa ... -
mybatis3.1分页自动添加总数
2013-07-08 21:11 22828问题 1.mybatis默认分页是内存分页的,谁用谁崩溃啊! ... -
Rop开发手册(1):最简单的服务开放平台框架
2012-08-08 11:35 8604Rop概述 Rop是Rapid Open Pl ... -
学习Spring必学的Java基础知识(9)----HTTP请求报文
2012-06-09 16:02 13922引述要学习Spring框架的技术内幕,必须事先掌握一些基本的J ... -
学习Spring必学的Java基础知识(8)----国际化信息
2012-05-26 11:19 28452引述要学习Spring框架的 ... -
学习Spring必学的Java基础知识(7)----事务基础知识
2012-05-26 10:57 5082引述要学习Spring框架的技术内幕,必须事先掌握一些基本的J ... -
学习Spring必学的Java基础知识(6)----ThreadLocal
2012-05-19 10:09 12120引述要学习Spring框架的 ... -
学习Spring必学的Java基础知识(5)----注解
2012-05-19 09:56 5774引述要学习Spring框架的技术内幕,必须事先掌握一些基本的J ... -
学习Spring必学的Java基础知识(4)----XML基础知识
2012-05-12 15:33 8556引述要学习Spring框架的 ... -
学习Spring必学的Java基础知识(3)----PropertyEditor
2012-05-12 15:13 16836引述要学习Spring框架的 ... -
明明白白AOP(傻瓜也会心领神会!)
2012-05-05 11:04 10577引子: AOP(面向方面编 ... -
学习Spring必学的Java基础知识(2)----动态代理
2012-05-02 13:03 9689引述要学习Spring框架的 ... -
学习Spring必学的Java基础知识(1)----反射
2012-04-25 13:57 89771引述要学习Spring框架的技术内幕,必须事先掌握一些基本的J ... -
透透彻彻IoC(你没有理由不懂!)
2012-04-18 11:01 94195引述:IoC(控制反转:I ... -
单元测试系列之5:使用unitils测试Service层
2012-04-14 10:48 18437引述:Spring 的测试框架为我们提供一个强大的测试环境,解 ... -
如何用Spring读取JAR中的文件
2012-04-13 17:22 18389使用如下方式读取JAR中的文件出错 类路径下 ... -
单元测试系列之4:使用Unitils测试DAO层
2012-04-12 16:32 19673Spring 的测试框架为我们提供一个强大的测试环境,解 ... -
单元测试系列之3:测试整合之王Unitils
2012-04-09 14:11 15635引述:程序测试对保障应用程序正确性而言,其重要性怎么样强调都不 ... -
单元测试系列之2:模拟利器Mockito
2012-03-30 11:38 15282引述:程序测试对 ... -
单元测试系列之1:开发测试的那些事儿
2012-03-28 12:52 10008引述:程序测试对保障应用程序正确性而言,其重要性怎 ...
相关推荐
本文将全面分析Spring中的编程式事务管理和声明式事务管理,旨在帮助开发者深入理解这两种事务管理方式,并在实际项目中合理选择。 **编程式事务管理** 编程式事务管理是通过代码直接控制事务的开始、提交、回滚等...
在"Spring事务传播Demo"中,我们可能看到如何在不同传播行为下,一个事务方法被另一个事务方法调用时,事务是如何管理和传播的。例如,一个PROPAGATION_REQUIRED的方法调用了一个PROPAGATION_REQUIRES_NEW的方法,...
事务传播行为(Propagation)定义了当一个事务方法被另一个事务方法调用时的行为。在Spring中,这些行为可以通过`TransactionDefinition`接口中的常量来指定。具体来说,`TransactionDefinition`定义了以下七种传播...
当我们遇到"AOP实现自我调用的事物嵌套问题"时,这通常涉及到Spring框架中的事务管理,特别是自调用方法在事务处理时可能会引发的问题。 首先,让我们理解Spring AOP的事务管理是如何工作的。Spring使用代理模式来...
Spring会创建一个代理对象来包裹被注解的方法,当调用这些方法时,实际上是在调用代理对象,从而实现事务的自动化管理。 在事务管理过程中,Spring通过`@EnableAspectJAutoProxy`注解启用AOP代理。AOP代理可以是JDK...
- **问题分析**:当事务方法被声明为非`public`时,Spring的AOP代理将无法正确识别这些方法,从而导致事务配置无效。 - **示例代码**: ```java @Service public class UserService { @Transactional private...
事务传播行为(Transaction Propagation)是Spring事务管理中一个关键的概念,用于定义在一个事务方法被调用时,如何与当前运行的事务进行交互。本文将深入探讨“Spring事物传播测试表”所涉及的知识点。 首先,...
} 在这个例子中,`UserService#logon()` 方法是事务方法,它调用了 `UserService#updateLastLogonTime()` 和 `ScoreService#addScore()` 两个方法。由于所有服务类都继承自 `BaseService`,我们可以假设它们都使用...
在Spring中,事务的传播行为是指当一个事务方法被另一个事务方法调用时,应该怎样处理这两个事务之间的关系。这个概念是通过`@Transactional`注解中的`propagation`属性来设置的。下面将详细讲解Spring事务的七个...
6. **数据库配置问题**:事务管理依赖于底层数据库支持,如MySQL的InnoDB引擎提供事务支持。如果数据库不支持事务,或者事务隔离级别设置不正确,事务特性将无法正常工作。 7. **懒加载异常**:在事务范围内,如果...
事务的传播行为定义了当方法调用时如何处理当前事务: - `PROPAGATION_REQUIRED`: 如果当前没有事务,则新建一个事务;如果已经存在一个事务中,则加入到这个事务中。 - `PROPAGATION_SUPPORTS`: 支持当前事务,如果...
Spring声明式事务主要依赖于AOP(面向切面编程)实现,它通过分析事务注解或XML配置,动态地织入事务管理代码。在声明式事务中,事务属性是非常关键的,它们决定了事务的行为。这些属性包括: 1. 事务的传播行为:...
Spring 提供了事务传播行为,当一个事务方法被另一个事务方法调用时,可以根据事务传播属性来决定如何处理当前事务。常见的传播行为包括: - REQUIRED(默认):如果当前存在事务,则加入当前事务;如果没有事务,...
Spring的声明式事务管理是基于AOP实现的,通过代理模式在方法调用前后插入事务处理代码。 8. **源码分析**: “spring_transaction_custom-master”项目可能包含了对Spring事务管理器的自定义实现,通过阅读源码...
Spring 事务传播行为是Spring框架中事务管理的重要组成部分,它定义了在多个方法相互调用时,事务如何在这些方法间传播。理解这些行为对于确保应用程序的事务一致性至关重要。接下来,我们将通过具体的案例来深入...
- **事务传播行为**:定义了当前方法调用时如何与现有的事务相结合。 - **事务隔离级别**:不同的事务隔离级别可以避免脏读、不可重复读等问题,但也可能引入性能上的开销。 - **事务回滚**:当事务执行过程中发生...
10.3 事务方法嵌套调用的迷茫 10.3.1 Spring事务传播机制回顾 10.3.2 相互嵌套的服务方法 10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的...