Spring注解风格的事务传播机制
来源:互联网 发布:如何看淘宝消费总额 编辑:程序博客网 时间:2024/04/28 21:01
原文地址:http://blog.csdn.net/liovey/article/details/14149137
概念
本地事务
数据库事务,默认事务为自动提交,因此如果一个业务逻辑类中有多次数据库操作将无法保证事务的一致性。
Spring事务
对本地事务操作的一次封装,相当于把使用JDBC代码开启、提交、回滚事务进行了封装。
上述两个概念会在demo中用到,以方便大家理解代码。
传播特性
该特性是保证事务是否开启,业务逻辑是否使用同一个事务的保证。当事务在传播过程中会受其影响。其传播特性包括:
1、Propagation.REQUIRED
方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。
2、Propagation.REQUIRES_NEW
无论何时自身都会开启事务
3、Propagation.SUPPORTS
自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务
4、Propagation.NOT_SUPPORTED
自身不会开启事务,在事务范围内使用挂起事务,运行完毕恢复事务
5、Propagation.MANDATORY
自身不开启事务,必须在事务环境使用否则报错
6、Propagation.NEVER
自身不会开启事务,在事务范围使用抛出异常
7、Propagation.NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。需要JDBC3.0以上支持。
实例Demo
Propagation.REQUIRED
测试入口代码
@Test public void testRequires(){ sService.addStudent(); }
Service代码
@Transactional(propagation = Propagation.REQUIRED) public void addStudent(){ String sql = "insert into student(name) values('st0')"; jdbcTemplate.execute(sql); tService.addTeacher(); throw new RuntimeException(); }
@Transactional(propagation = Propagation.REQUIRES)public void addTeacher(){ String sql = "insert into teacher(name) values ('t5')"; jdbcTemplate.execute(sql);}经测试无论在tService还是sService如果不抛出异常,那么数据提交成功,如果抛出异常,数据提交失败。这说明tService和sService使用的是同一个事务,并且只要方法被调用就开启事务。
Propagation.REQUIRES_NEW
测试入口代码
//无论何时自身都会开启事务@Testpublic void testRequiresNew(){ sService.addStudent5();}
Service代码
@Transactional(propagation = Propagation.REQUIRES_NEW)public void addStudent5(){ String sql = "insert into student(name) values('st5')"; jdbcTemplate.execute(sql); tService.addTeacher5(); throw new RuntimeException();}
@Transactional(propagation = Propagation.REQUIRES_NEW)public void addTeacher5(){ String sql = "insert into teacher(name) values ('t5')"; jdbcTemplate.execute(sql);}
经测试如果在addStudent5中抛出异常,学生数据不能正确提交,教师信息被正确提交。说明sService和tService是在两个独立的事务中运行,并且只要方法被调用就开启事务。
Propagation.SUPPORTS
测试入口代码
//自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务@Testpublic void testSupport(){ sService.addStudent6();}Service代码
@Transactional(propagation = Propagation.SUPPORTS)public void addStudent6(){ String sql = "insert into student(name) values('st6')"; jdbcTemplate.execute(sql); tService.addTeacher6(); throw new RuntimeException();}
@Transactional(propagation = Propagation.SUPPORTS)public void addTeacher6(){ String sql = "insert into teacher(name) values ('t6')"; jdbcTemplate.execute(sql);}
经测试如果在addStudent6中抛出异常,学生数据和教师数据都被正确提交。说明sService和tService没有被spring管理和开启事务,而是使用了本地事务,由于本地事务默认自动提交因此数据都提交成功,但它们使用的却不是同一个事务,一旦出现异常将导致数据的不一致。
Propagation.NOT_SUPPORTED
测试入口代码
//自身不会开启事务,在事务范围内使用挂起事务,运行完毕恢复事务@Testpublic void testNotSupport(){ sService.addStudent4();}Service代码
@Transactional(propagation = Propagation.NOT_SUPPORTED)public void addStudent4(){ String sql = "insert into student(name) values('st4')"; jdbcTemplate.execute(sql); throw new RuntimeException();}经测试如果在addStudent4中抛出异常,学生数据正确提交。说明sService没有被spring管理和开启事务,而是使用了本地事务,由于本地事务默认自动提交因此数据都提交成功。
测试入口代码
//自身不会开启事务,在事务范围内使用挂起事务,运行完毕恢复事务@Testpublic void testNotSupport1(){ sService.addStudent();}Service代码
@Transactional(propagation = Propagation.REQUIRED)public void addStudent(){ String sql = "insert into student(name) values('st0')"; jdbcTemplate.execute(sql); tService.addTeacher4();}
@Transactional(propagation = Propagation.NOT_SUPPORTED)public void addTeacher4(){ String sql = "insert into teacher(name) values ('t4')"; jdbcTemplate.execute(sql); throw new RuntimeException();}经测试如果在addTeacher4中抛出异常,学生数据提交失败,教师数据提交成功。说明sService开启了事务,tService没有开启事务,而是使用了本地事务。
Propagation.MANDATORY
测试入口代码
//自身不开启事务,必须在事务环境使用否则报错@Testpublic void testMandatory(){ sService.addStudent1();}Service代码
@Transactional(propagation = Propagation.MANDATORY)public void addStudent1(){ String sql = "insert into student(name) values('st1')"; jdbcTemplate.execute(sql);}
经测试代码报错。
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory',没有找到事务环境。
Propagation.NEVER
测试入口代码
//自身不会开启事务,在事务范围使用抛出异常@Testpublic void testNever(){ sService.addStudent();}Service代码
<span style="font-size:14px">@Transactional(propagation = Propagation.REQUIRED)public void addStudent(){ String sql = "insert into student(name) values('st0')"; jdbcTemplate.execute(sql); tService.addTeacher3();}</span>
@Transactional(propagation = Propagation.NEVER)public void addTeacher3(){ String sql = "insert into teacher(name) values ('t3')"; jdbcTemplate.execute(sql);}经测试代码报错,由于sService开启了事务,当调用sService方法时由于其传播特性为never,因此报存在事务错误。
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
Propagation.NESTED
测试入口代码
//如果没有事务环境其特性同Propagation.REQUIRED,否则嵌套运行事务@Testpublic void testNested(){ sService.addStudent2();}Service代码
@Transactional(propagation = Propagation.NESTED)public void addStudent2(){ String sql = "insert into student(name) values('st2')"; jdbcTemplate.execute(sql); tService.addTeacher2(); throw new RuntimeException();}
@Transactional(propagation = Propagation.NESTED)public void addTeacher2(){ String sql = "insert into teacher(name) values ('t2')"; jdbcTemplate.execute(sql);}
经测试代码报错,教师数据和学生数据都没有提交成功。说明其按照REQUIRED特性运行。对于嵌套事务,大家可以模拟两个数据源,一方的失败不会影响另一方。
- Spring注解风格的事务传播机制
- spring事务的传播机制
- Spring事务传播机制
- Spring事务传播机制
- Spring事务传播机制
- spring事务传播机制
- Spring事务传播机制
- Spring事务传播机制
- Spring 事务传播机制
- spring事务传播机制
- Spring事务传播机制
- spring 事务传播机制
- Spring事务传播机制
- Spring事务传播机制
- Spring事务传播机制
- Spring事务传播机制
- spring事务传播机制
- Spring事务传播机制
- 解决 安装后的 且安装在子级目录的dedecms 转移到根目录的问题
- 这样扫地的时候可以方便扫垃圾
- C# 结构体初始化, 求为空
- 非机动车道适合于自行车
- 她一定会为祖国的迅猛发展感到骄傲
- Spring注解风格的事务传播机制
- 一天夜里我梦见我来到了草莓世界
- lua之metatable
- log4j的简单的例子~以及使用log4j和不使用log4j的对比
- 表现出自己的快乐个性
- 功夫不负有心人小强终于变成了新一带的快乐歌神
- Lable 的宽 高自适应
- 有的像全身长满了爪子的蜘蛛
- for循环中i++与++i的效率探究