数据库程序接口——JDBC——功能第四篇——事务之Spring事务
综述
事务的实现方式有三种,JTA,Spring事务,Web Container方式。本篇讲述Spring事务。
Spring事务分为两个部分核心对象,Spring事务的实现方式。
Spring事务实现的方式有三种。声明式,注解式,代码的方式。声明方式在实际项目中运用比较广泛,注解方式需要在每个方法上添加@Transactional注解,代码冗余度比较高。代码方式只是为了更好的理解Spring事务的机制,在实际项目中并不适用。
核心对象
PlatformTransactionManager
事务管理接口。
- Transaction getTransaction(transactionDefinition) :通过事务定义对象获取事务
- commit(transactionStatus):提交事务
- rollback(transactionStatus):回滚事务。
TransactionDefinition
事务的属性或定义对象。包含的属性如下:
Isolation:事务的隔离级别。
- TRANSACTION_NONE:表示不支持事务。值为0,
- TRANSACTION_READ_UNCOMMITED:表示一个事务可以读取另外事务未提交的数据。存在脏读。值为1
- TRANSACTION_READ_COMMITED:表示只读取已提交的数据。防止脏读。存在重复读,幻读。值为2
- TRANSACTION_REPEATABLE_READ:表示在读取过程中不允许修改操作。防止一个事务多次查询得到不同的值。防止脏读,重复读,存在虚读。值为4
- 当为TRANSACTION_SERIALIZABLE:TODO,值为8.
Propagation:事务的传播机制。
- Never:表示没有事务。
- NOT SUPPORT:表示不支持事务。
- REQUIRED:为每个方法的事务创建一个域(Scope),内部方法共享外部方法的域,内部方法可以在自己的域内回滚事务,此时外部方法的事务不受内部方法事务的影响,外部事物依然可以提交。但是外部事物会捕获到UnexeceptedRollBackException。类似于语言中的函数,或方法,内部方法有自己独立的域,外部方法也有自己独立的域,内部方法可以访问外部方法的变量等等。
- REQUIRED NEW:为每个方法创建一个事务,彼此无关联。
- NESTED:为外部方法创建一个事务,多个存档点。内部方法与外部方法在同一事务内。
Timeout:超时时间。
read-only:是否是只读的事务。
TransactionStatus
表示一个新创建的事务或者已存在的事务。
- isNewTransaction:是否是新事务。
- hasSavepoint:事务是否有存放点
- setRollbackOnly:回滚事务
- isRollbackOnly:TODO
- flush:TODO
- isCompleted:事务是否执行完成。
代码示例如下:
//第一步:创建事务属性对象TransactionDefinition,创建事务管理对象TransactionManager。
// 创建事务属性对象
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("trans1");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 创建事务管理对象
DataSourceTransactionManager transcationManager = new DataSourceTransactionManager(); //第二步:获取事务对象,
TransactionStatus status = transcationManager.getTransaction(def);
//第三步:实现业务逻辑代码
try
{
// 代码逻辑
}
catch(Exception e)
{
transcationManager.rollback(status);
throw e;
}
transcationManager.commit(status);
实现方式
spring事务实现的方式有三种。配置切面方式,注解方式,代码方式。配置切面方式在实际项目中运用比较广泛,注解方式需要在每个方法上添加@Transactional注解,代码冗余度比较高。代码方式只是为了更好的理解Spring事务的机制,在实际项目中并不适用。
配置切面方式
第一步:配置事务管理。
<!-- 配置事务管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property>
</bean>
第二步:通过”tx:advice”标签配置事务的场景。指定在哪些方法上配置事务,以及这些事务的定义。tx:advice包含一个或多个tx:attribtue,tx:attribute包含一个或多个tx:method。tx:method标签配置具体的事务。
tx:method的属性有
- name:表示方法的名称,可以使用通配符。例如get*表示以get开头的方法,如果配置多个,使用逗号隔开。
- isolation:配置事务的隔离级别。参考TransactionDefinition
- propagation:配置事务的传播机制。传播机制的种类如下:
- rollbackFor:指定运行时让事务回滚的异常。这些异常必须是运行时异常,而且需要指定异常类的全路径名。默认情况下,只要运行时出现异常,就回滚事务。
- noRollbackFor:指定运行时不会让事务回滚的异常。
- timeout:表示超时时间,事务执行超过当前时间,事务自动回滚。默认值为-1,表示永不超时。
示例如下:
<tx:advice id="txAdvice">
<tx:attributes>
<!--方法名称以get开头的事务为只读事务,隔离级别为SERIALIZABLE-->
<tx:method name="get*" read-only="true" isolation="SERIALIZABLE" />
<!--方法名称以insert开头的事务,隔离级别为SERIALIZABLE,传播机制为REQUIRED,当发生TestException时回滚事务,ArithmeticException不会回滚事务。-->
<tx:method name="insert*" isolation="SERIALIZABLE" timeout="20" propagation="REQUIRED"
rollback-for="com.rain.exception.TestException"
no-rollbackfor="java.lang.ArithmeticException" />
<tx:method name="*" isolation="READ_COMMITTED" />
</tx:attributes>
</tx:advice>
第三步:通过aop:config配置事务切面。aop:config包含一个或多个(aop:pointcut,aop:advisor)。aop:pointcut指定为哪些类配置切面,aop:advisor将tx:advice与aop:pointcut关联起来。其中aop:config标签中expression的格式为:execution(* packageName.className.*(..))。它是SPEL表达式。
示例如下:
<aop:config>
<aop:pointcut expression="execution(* com.rain.service.*.*(..))" id="studentServiceMethod" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="studentServiceMethod" />
</aop:config>
如果配置多个事务,重复上述步骤。也可以在aop:config中配置多组(aop:pointcut,aop:advisor)。
第四步:验证。使用Log4J日志,将级别设置为DEBUG。启动时,会加载事务的配置。
2017-05-30 12:22:00 DEBUG NameMatchTransactionAttributeSource:96 - Adding transactional method [get*] with attribute [PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,readOnly] 2017-05-30 12:22:00 DEBUG NameMatchTransactionAttributeSource:96 - Adding transactional method [insert*] with attribute [PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE,timeout_20,-com.rain.exception.TestException,+java.lang.ArithmeticException] 2017-05-30 12:22:00 DEBUG NameMatchTransactionAttributeSource:96 - Adding transactional method [*] with attribute [PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED]
运行insertXX方法时,显示事务处理的详细过程。
2017-05-30 11:49:57 DEBUG DataSourceTransactionManager:367 - Creating new transaction with name [com.rain.service.impl.StudentServiceImpl.insertStudent]: PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE,timeout_20,-com.rain.exception.TestException,+java.lang.ArithmeticException。 2017-05-30 11:49:58 TRACE TransactionInterceptor:517 - Completing transaction for [com.rain.service.impl.StudentServiceImpl.insertStudent] after exception: java.lang.ArithmeticException: / by zero 2017-05-30 11:49:58 TRACE RuleBasedTransactionAttribute:131 - Applying rules to determine whether transaction should rollback on java.lang.ArithmeticException: / by zero 2017-05-30 11:49:58 TRACE RuleBasedTransactionAttribute:148 - Winning rollback rule is: NoRollbackRuleAttribute with pattern [java.lang.ArithmeticException] 2017-05-30 11:49:58 DEBUG DataSourceTransactionManager:759 - Initiating transaction commit
2017-05-30 11:49:58 DEBUG DataSourceTransactionManager:310 - Committing JDBC transaction on Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@25df00a0]
2017-05-30 11:49:58 TRACE TransactionSynchronizationManager:331 - Clearing transaction synchronization
当insertXX方法有java.lang.ArithmeticException异常时。不会回滚事务。
2017-05-30 12:09:17 TRACE RuleBasedTransactionAttribute:131 -
Applying rules to determine whether transaction should rollback on java.lang.ArithmeticException: / by zero
2017-05-30 12:09:17 TRACE RuleBasedTransactionAttribute:148 - Winning rollback rule is: NoRollbackRuleAttribute with pattern [java.lang.ArithmeticException]
当insertXX方法中有TestException异常时。回滚事务。
Applying rules to determine whether transaction should rollback on com.rain.exception.TestException: 这是测试用的异常
2017-05-30 12:22:01 TRACE RuleBasedTransactionAttribute:148 - Winning rollback rule is: RollbackRuleAttribute with pattern [com.rain.exception.TestException]
2017-05-30 12:22:01 DEBUG DataSourceTransactionManager:851 - Initiating transaction rollback
2017-05-30 12:22:01 DEBUG DataSourceTransactionManager:325 - Rolling back JDBC transaction on Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@aba625]
注解方式
第一步:配置事务管理。与声明式事务完全相同。参考配置切面方式第一步
第二步:通过tx:annotation-driven配置事务支持注解方式。tx:annotation-driven的属性有
- transaction-manager:指定事务管理的名称,默认值为transactionManager。所以当名称为transactionManager时,可以忽略。
- mode:注解的模式,模式有两种,proxy与aspectj,默认方式为proxy。
- proxy-target-class:识别注解的方式。@Transactional可以在接口的方法上,也可以在具体类的方法上。当设置为false时,既可以识别具体类上的@Transactional注解,也可以识别接口上的@Transactional。当为true时,接口上的@Transactional将被忽略。默认值为false。
- order:TODO。
示例如下:
<!-- 配置注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager" mode="proxy" proxy-target-class="true"/>
第三步:在方法上加@Transactional注解,该注解属性的含义如下:
- value:表示事务管理器的名称,如果配置中存在多个事务管理器,trans1,trans2。value值用来指定当前事务所属的事务管理器。
- isolation:事务的隔离级别。参考事务隔离级别,默认值为READ_COMMITED。
- propagation:事务的传播机制,参考事务传播机制
- readOnly:是否是只读事务。true表示是,false表示否,默认值为false。
- rollbackFor:指定发生哪些异常时,事务回滚,默认值为Exception.class。异常类型为运行时异常
- rollbackForClassName:含义与rollbackFor相同,值为异常类的名称字符串。
- noRollbackFor:指定发生哪些异常时,事务不会回滚,无默认值
- noRollbackForClassName:含义为noRollbackFor相同,值为异常类的名称字符串。
@Transactional(propagation=Propagation.REQUIRED,isolation = Isolation.SERIALIZABLE,timeout=20,rollbackFor = {com.rain.exception.TestException.class},
noRollbackFor = {java.lang.ArithmeticException.class})
第四步:验证。在运行该方法时。会加载事务属性,并创建事务。
2017-05-30 14:06:57 DEBUG AnnotationTransactionAttributeSource:116 -
Adding transactional method 'com.rain.service.impl.StudentServiceImpl.insertStudent' with attribute: PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE; '',-com.rain.exception.TestException,-java.lang.NullPointerException,+java.lang.ArithmeticException 2017-05-30 14:06:57 DEBUG DataSourceTransactionManager:367 -
Creating new transaction with name [com.rain.service.impl.StudentServiceImpl.insertStudent]: PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE; '',-com.rain.exception.TestException,-java.lang.NullPointerException,+java.lang.ArithmeticException
当发生TestException时,事务回滚。
2017-05-30 14:06:57 TRACE RuleBasedTransactionAttribute:131 - Applying rules to determine whether transaction should rollback on com.rain.exception.TestException: 这是测试用的异常
2017-05-30 14:06:57 TRACE RuleBasedTransactionAttribute:148 - Winning rollback rule is: RollbackRuleAttribute with pattern [com.rain.exception.TestException]
当发生ArithmeticException时,事务不会回滚。
2017-05-30 12:09:17 TRACE RuleBasedTransactionAttribute:131 - Applying rules to determine whether transaction should rollback on java.lang.ArithmeticException: / by zero
2017-05-30 12:09:17 TRACE RuleBasedTransactionAttribute:148 - Winning rollback rule is: NoRollbackRuleAttribute with pattern [java.lang.ArithmeticException]
代码方式
代码实现事务的方式有两种,一种是TransactionTemplate,该对象可以设置事务的属性。另外一种是TransactionManager方式。TransactionManager方参考核心对象下面的代码示例。
TransactionTemplate方式
第一步:初始化TransactionTemplate,
// 创建事务template类
private final TransactionTemplate tranTemp; // 创建学生的service类
@Autowired
private IStudentService studentService; // 在构造器中初始化TransactionTemplate
public TransactionServiceImpl(PlatformTransactionManager tranManager) {
Assert.notNull(tranManager, "The 'tranManager' argument must not be null ");
this.tranTemp = new TransactionTemplate(tranManager);
}
第二步:调用transactionTemplate的execute方法,参数为TransactionCallback,或者是TransactionCallbackWithoutResult,前者返回类型为void,后者有返回类型。
无返回类型TransactionCallbackWithoutResult
// 通过代码的方式实现事务
@Override
public void insertStudent(Student stu) {
tranTemp.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
// 代码逻辑
} catch (Exception e) {
e.printStackTrace();
status.setRollbackOnly();
}
}
});
}
有返回类型TransactionCallback<T>
public void insertStudentWithReturn(Student stu)
{
tranTemp.execute(new TransactionCallback<Student>() {
@Override
public Student doInTransaction(TransactionStatus status) {
try
{
// 代码逻辑
}catch(Exception e)
{
e.printStackTrace();
// 回滚事务
status.setRollbackOnly();
}
return stu;
}});
}
至此本篇内容结束
数据库程序接口——JDBC——功能第四篇——事务之Spring事务的更多相关文章
- 数据库程序接口——JDBC——功能第五篇——批量处理
综述 批量处理一般指批量插入,批量更新,删除通过可以指定where条件实现.批量插入的实现方式有三种类型.statement,preparedStatement,callableStatement. ...
- 数据库程序接口——JDBC——功能第一篇——第一个程序
流程图 综述 从零开始搭建JDBC环境.通过创建Java项目,在项目中,通过java程序执行SQL,并处理返回的结果.本文通过执行 select 1 from dual 语句来测试,并输出相结果集.首 ...
- 数据库程序接口——JDBC——功能第二篇——数据源之C3P0数据源
综述 C3P0由三部分内容组成.实例化对象,各配置项的含义,以及加载配置项的方式. 实例化对象的方式有三种,第一种方式直接new ComboPooledDataSource,第二种方式使用工厂类Dat ...
- 数据库程序接口——JDBC——API解读第一篇——建立连接的核心对象
结构图 核心对象 Driver Java通过Driver接口表示驱动,每种类型的数据库通过实现Driver接口提供自己的Driver实现类. Driver由属性,操作,事件三部分组成. 属性 公共属性 ...
- 数据库程序接口——JDBC——API解读第二篇——执行SQL的核心对象
结构图 核心对象 Statement Statement主要用来执行SQL语句.它执行SQL语句的步骤为: 第一步:创建statement对象. 第二步:配置statement对象,此步骤可以忽略. ...
- 数据库程序接口——JDBC——初篇——目录
目录 建立连接 核心对象 Driver DriverManager Connection DataSource 常用功能 第一个程序 C3P0数据源 DBCP数据源 事务之Spring事务 执行SQL ...
- 数据库程序接口——JDBC——API解读第三篇——处理结果集的核心对象
核心对象 处理结果集的核心对象有ResultSet和RowSet.其中ResultSet指定关系型数据库的结果集,RowSet更为抽象,凡是由行列组成的数据都可以. ResultSet ResultS ...
- 数据库事务和spring事务的区别
数据库事务和spring事务 本质上其实是同一个概念,spring的事务是对数据库的事务的封装,最后本质的实现还是在数据库,假如数据库不支持事务的话,spring的事务是没有作用的.数据库的事务说简单 ...
- 【Spring】Spring的事务管理 - 1、Spring事务管理概述(数据库事务、Spring事务管理的核心接口)
Spring事务管理概述 文章目录 Spring事务管理概述 数据库事务 什么是Spring的事务管理? Spring对事务管理的支持 Spring事务管理的核心接口 Platform Transac ...
随机推荐
- AspxGridView 客户端点击获取对应的列值
Html 内容: <dx:ASPxGridView ID="ASPxGridViewCluster" runat="server" Width=" ...
- Redis 数据库使用和搭建
1.redis中文网 http://www.redis.cn/documentation.html 2.数据类型介绍 http://redis.cn/topics/data-types-intro.h ...
- SpringMVC起步
SpringMVC: SpringMVC是Spring的一个组件,作为控制器,可以替代Servlet SpringMVC的开发过程: 请求发送 DispatcherServlet查询一个或多个Hand ...
- javascript入门(1)
目录 Javascript认识(1) JavaScript 常见事宜 JavaScript介绍 Javascript内容 Javascript书写位置 变量 变量是什么 变量的命名规则 变量提升 数据 ...
- COS上传图片和显示图片
写这篇文章之前,我也是刚刚实现COS上传和显示图片.我百度了好多相关文章,COS上传图片成功的文章不少,上传后显示图片的文章几乎没有.于是写一篇记录下. COS上传图片推荐链接:https://blo ...
- Codeforces Round #614 (Div. 2) C - NEKO's Maze Game
题目链接:http://codeforces.com/contest/1293/problem/C 题目:给定一个 2*n的地图,初始地图没有岩浆,都可以走, 给定q个询问,每个询问给定一个点(x,y ...
- Controller-->View传值的几种方法
Controller --- > View 传值的方法 ViewBag ViewData TempData 向普通View页面传一个Model对象 向强类型页面传传一个Model对象 用一个Vi ...
- 2.spring源码-BeanPostProcessor后置处理之ApplicationContextAwareProcessor,实现spring容器中某一个类的bean对象在初始化时需要得到Spring容器内容。
需求:我们的需求是,在spring初始化完毕时,使我们自定义一个类Bird类可以得到spring容器内容. 实现步骤: 1.首先我们来看一下ApplicationContextAwareProcess ...
- tkinter页面卡死
tkinter界面卡死的解决办法 1.如果点击按钮,运行了一个比较耗时的操作,那么界面会卡死 import tkinter as tk import time def onclick(text, ...
- 剑指offer系列——59/60.按之字形顺序打印二叉树/把二叉树打印成多行
Q:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推. A:BFS,偶数层reverse vector&l ...