Spring事务传播特性实例解析(以及如何使用注解形式事务)
原文地址:http://blog.csdn.net/yoara/article/details/16114853
原文地址的文章,写的demo会误导读者,所以在原文地址文章的基础上对原作者的demo进行修改,让demo浅显易懂。
Demo说明
采用Junit4.10.0+Spring4.2.0+Spring JDBCTemplate+mysql5.1.51(数据库表的存储引擎使用 InnoDB,MyISAM存储引擎是不支持事务的),通过注解方式配置事务,代码层次包括主测试类,两个Service对象,事务在Service开启。
事务概念
注意:从原文地址中,COPY 过来的。
本地事务
数据库事务,默认事务为自动提交,因此如果一个业务逻辑类中有多次数据库操作将无法保证事务的一致性。
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以上支持。
代码实例
代码说明,两个 实例类,InsertPassword 、 InsertUser, InsertPassword类中的insertPassWord方法 调用了 InsertUser类中的 insertUser 方法。
测试代码
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.sky.lp.AAtestTransaction.InsertPassword;public class TestJunit {@Testpublic void testTransaction() {ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-servlet.xml");InsertPassword t = (InsertPassword)appCtx.getBean("insertPassword");t.insertPassWord();}}
InsertPassword类代码
package com.sky.lp.AAtestTransaction;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Component
public class InsertPassword {@Autowiredprivate JdbcTemplate jdbc;@Autowiredprivate InsertUser insertUser;@Transactional(propagation = Propagation.REQUIRED)public void insertPassWord() {String[] sql = new String[2];sql[0] = "INSERT INTO PASSWORD (USERID, PASSWORD, CREATE_TIME) VALUES ('1','qwe', now())";jdbc.execute(sql[0]);insertUser.insertUser();throw new RuntimeException("抛错");}}
InsertUser类代码
package com.sky.lp.AAtestTransaction;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;@Component
public class InsertUser {@Autowiredprivate JdbcTemplate jdbc;@Transactional(propagation = Propagation.REQUIRED)public void insertUser() {String[] sql = new String[2];sql[0] = "INSERT INTO user (name, age, CREATE_TIME) VALUES ('123456789','25', now())";jdbc.execute(sql[0]);}}
spring-servlet.xml 配置文件
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"><!-- 启动包扫描功能,以便注册带有@Controller、@Service、@repository、@Component等注解的类成为spring的bean --><context:annotation-config /><context:component-scan base-package="com.sky.lp.AAtestTransaction" /><!-- 定义数据源 使用 c3po 包 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close"><property name="name" value="druidOne" /><property name="url" value="jdbc:mysql://localhost:3306/littledemo" /><property name="username" value="root" /><property name="password" value="laixu785^@#"></property><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="initialSize" value="2" /><property name="maxActive" value="10" /><property name="minIdle" value="5" /><property name="validationQuery" value="SELECT COUNT(*) FROM DUAL" /><property name="testWhileIdle" value="true" /><property name="timeBetweenEvictionRunsMillis" value="5000" /></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><!-- 事务控制 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><tx:annotation-driven transaction-manager="transactionManager" /></beans>
传播特性 Propagation.REQUIRED
在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。
经测试无论在insertPassWord方法还是insertUser方法,如果有一个方法抛出运行时异常,数据提交失败。 这说明insertPassWord和insertUser使用的是同一个事务,并且只要方法被调用就开启事务。
传播特性 Propagation.REQUIRES_NEW
在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRES_NEW)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.REQUIRES_NEW)。
经测试无论在insertPassWord方法还是insertUser方法,如果其中一个方法抛出运行时异常,不会影响另一个方法事务的数据提交。 这说明insertPassWord和insertUser使用的是不的同事务。
传播特性 Propagation.SUPPORTS
在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.SUPPORTS)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.SUPPORTS)。
经测试如果在insertPassWord中抛出异常,password数据和user数据都被正确提交。说明insertPassWord和insertUser没有被spring管理和开启事务,而是使用了本地事务,由于本地事务默认自动提交因此数据都提交成功,但它们使用的却不是同一个事务,一旦出现异常将导致数据的不一致。
传播特性 Propagation.NOT_SUPPORTED
在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.NOT_SUPPORTED)。
方法 insertPassWord 注释掉 抛错代码,insertUser 在方法末尾 添加
throw new RuntimeException("抛错");
经测试如果在insertUser 中抛出异常,passwrod数据提交失败,user数据提交成功。说明insertPassWord开启了事务,insertUser没有开启事务,而是使用了本地事务。
传播特性 Propagation.MANDATORY
在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.SUPPORTS)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.MANDATORY)。
insertPassWord 方法 和 insertUser 方法 都注释掉 抛错 代码
经测试报错
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
说明 方法 insertUser 必须在事务内执行。
传播特性 Propagation.NEVER
在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.NEVER)。
insertPassWord 方法 和 insertUser 方法 都注释掉 抛错 代码
经测试报错
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
说明 方法 insertUser 不能在事务内执行。
传播特性 Propagation.NESTED
在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.NESTED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.NESTED)。
方法 insertPassWord在方法末尾添加
throw new RuntimeException("抛错");
经测试代码报错,user数据和password数据都没有提交成功。说明其按照REQUIRED特性运行。对于嵌套事务,大家可以模拟两个数据源,一方的失败不会影响另一方。
Spring事务传播特性实例解析(以及如何使用注解形式事务)相关推荐
- Spring事务传播特性实例解析
背景介绍 目前系统正在进行代码重构前期预研工作,目标采用spring控制事务以减少开发代码量,提高开发效率.同时避免开发人员编码控制事务所带来的链接没有释放,事务没有提交,出现异常事务没有回滚的Bug ...
- spring 事务传播行为实例分析
Spring事务传播行为: spring特有的事务传播行为,spring支持7种事务传播行为,确定客户端和被调用端的事务边界(说得通俗一点就是多个具有事务控制的service的相互调用时所形成的复杂的 ...
- 什么是事务、事务特性、事务隔离级别、spring事务传播特性
1.什么是事务: 事务是指程序中的一个操作序列.其特点是:该序列的所有操作要么全部成功完成,要么只要有一个操作失败,则该序列所有操作都将被撤销.这也是事务的原子性(要么成功,要么失败). 2.事务特性 ...
- java spring 事务传播_spring事务传播机制实例讲解
天温习spring的事务处理机制,总结如下 对于SQL事务的概念以及ACID性质,可以参见我的另一篇博文 http://kingj.iteye.com/admin/blogs/1675011 spri ...
- Spring 事务传播机制 实例讲解
事务传播机制 对于SQL事务的概念以及ACID性质,可以参见我的另一篇博文 http://kingj.iteye.com/admin/blogs/1675011 spring的管理的事务可以分为如下2 ...
- spring中事务传播特性
转载:若水三千-LOVE 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring 支持 7 种事务传播行为(Transaction Propagation Behavior ...
- Spring 事物传播特性
Spring 事物传播特性 这是Spring官方的定义 一共有7种 摘自源码省略了一部分 public interface TransactionDefinition {int PROPAGATION ...
- mysql数据库事务传播特性_什么是事务的传播特性?
我们都知道事务的概念,那么事务的传播特性是什么呢?(此处着重介绍传播特性的概念,关于传播特性的相关配置就不介绍了,可以查看spring的官方文档) 在我们用SSH开发项目的时候,我们一般都是将事务设置 ...
- Spring事务传播机制大白话(使用springboot,注解演示)
1. 我对传播机制的理解 为什么需要传播机制? 因为事务之间可能存在相互调用,例如service业务层的方法存在相互调用,如果相互调用的方法都开启了事务(对应到springboot就是在方法上要添加@ ...
最新文章
- BCH半月热点事件回顾
- stm32与arm7比较(经典)
- JavaScript中字符串去掉特殊字符和转义字符
- jsp mysql驱动程序_JSP通过JDBC驱动MySQL数据库方法
- CodeForces - 1440E Greedy Shopping(线段树)
- 筛选装置用c语言编程,一种空壳瓜子筛选装置的制作方法
- 关于如何清除某个特定网站的缓存---基于Chrome浏览器
- 网络世界在某种程度上助长了人格的分裂
- Atitit 集成之道 attilax著 1. 所谓系统集成(SI,System Integration),	1 2. 发展方向	1 2.1. 产品技术服务型	2 2.2. 系统咨询型	2 2.3.
- base64 img图片按父div等比例显示
- Jmeter下载安装详细步骤(2021)
- 还能这样玩——关于一些OI的黑(sao)科(cao)技(zuo)优化
- xray安全漏洞检测(高效能)
- 计算机第三课细心小编辑教案,教案-第6课小小编辑师
- Unity5.1 新的网络引擎UNET(一) 概括1
- 斜杠青年:人生的多种可能
- windowsmobile软件_经验:CSPJ/S初赛知识点整理(NOIP硬件与软件基础)
- TOP 云平台虚拟机内外网互通
- c语言象棋教程下载,C语言程序源代码中国象棋.doc-资源下载在线文库www.lddoc.cn...
- php redis pipeline管道技术
热门文章
- 杭电计算机学院吴迅冬,活动预告 | 叮~ 欢迎收看杭电Running Man
- linux 动态密码,LINUX使用一次性密码配置
- python猴子吃桃递归_Python猴子吃桃题源码​:请问第一天摘了多少桃?
- 关于DecimalFormat的取舍问题,DecimalFormat四舍五入的坑
- vue组件强制刷新的方案
- 数据管理解决方案 | 零售行业如何搭建全渠道大数据平台?
- 国家2020年区划数据爬取
- matlab振动响应,基于MatLab的车辆振动响应幅频特性分析-中原工学院学报.PDF
- 配电房轨道式智能巡视机器人_HT-TSX-600-配电房轨道机器人视频巡检系统
- 我的助理辞职了——给不听话的下属看看