8 -- 深入使用Spring -- 6...1 Spring支持的事务策略
8.6.1 Spring支持的事务策略
Java EE应用的传统事务有两种策略:全局事务和局部事务。全局事务由应用服务器管理,需要底层服务器的JTA(Java Transaction API)支持。局部事务和底层所采用的持久化技术有关,当采用JDBC持久化技术时,需要使用Connection队形来操作事务;而采用Hibernate持久化技术时,需要使用Session对象来操作事务。
全局事务可以跨多个事务性资源(典型例子是关系数据库和消息队列);使用局部事务,应用服务器不需要参与事务管理,因此不能保证跨多个事务性资源的事务的正确性。当然,实际上大部分应用都使用单一的事务性资源。
当采用传统的事务编程策略时,程序代码必然和具体的事务操作代码耦合,这样造成的后果是:当应用需要在不同的事务策略之间切换时,不须手动修改程序代码。如果使用Spring事务管理策略,就可以改变这种现状。
Spring 事务策略是通过PlatformTransactionManager接口体现的,该接口是Spring事务策略的核心。
该接口的源代码如下:
package edu.pri.lime._8_6_1.sourcecode; import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus; public interface PlatformTransactionManager { // 平台无关的获得事务的方法
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; // 平台无关的事务提交方法
void commit(TransactionStatus status) throws TransactionException; // 平台无关的事务回滚方法
void rollback(TransactionStatus status) throws TransactionException;
}
PlatformTransactionManager是一个与任何事务策略分离的接口,随着底层不同事务策略的切换,应用必须采用不同的实现类。PlatformTransactionManager接口没有与任何事务性资源捆绑在一起,它可以适应于任何事务策略,结合Spring的IoC容器,可以向PlatformTransactionManager注入相关的平台特性。
PlatformTransactionManager接口有许多不同的实现类,应用程序面向与平台无关的接口编程,当底层采用不同的持久层技术时,系统只需要使用不同的PlatformTransactionManager实现类即可 ------ 而这种切换通常由Spring容器负责管理,应用程序即无须与具体的事务API耦合,也无须与特定实现类耦合,从而将应用和持久化技术、事务API彻底分离开来。
提示:
Spring 的事务机制是一种典型的策略模式,PlatformTransactionmanager代表事务管理接口,但它并不知道底层到底如何管理事务,它只要求事务管理需要提供开始事务(getTransaction())、提交事务(commit())和回滚事务(rollback())三个方法,但具体如何实现则交给其实现类来完成 ------ 不同的实现类则代表不同的事务管理策略。
即使使用容器管理的JTA,代码也依然无须执行JNDI查找,无须与特定的JTA资源耦合在一起,通过配置文件,JTA资源传给PlatformTransactionManager的实现类。因此,程序的代码可在JTA事务管理和非JTA事务管理之间轻松切换。
注意:
Spring完全支持夸多个事务性资源的全局事务,前提是底层的应用服务器(如WebLogic、JBoss等)支持JTA全局事务。可以这样说:Spring本身并没有任何事务支持,它只是负责包装底层的事务 ------ 应用程序面向PlatformTransactionManager接口编程时,Spring在底层负责将这些操作转换成具体的事务操作代码,因此应用的底层支持怎样的事务策略,那么Spring就可支持怎样的事务策略。Spring事务管理的优势是将应用从具体的事务API中分离出来,而不是真正提供事务管理的底层实现。
在PlatformTransactionManager接口内,包含一个getTransaction(TransactionDefinitiondefinition)方法,该方法根据TransactionDefinition参数返回一个TransactionStatus对象。TransactionStatus对象表示一个事务,TransactionStatus被关联在当前执行的线程上。
getTransaction(TransactionDefinition definition)返回的TransactionStatus对象,可能是一个新的事务,也可能是一个已经存在的事务对象。如果当前执行的线程已经处于事务管理下,则返回当前线程的事务对象;否则,系统将新建的一个事务对象后返回。
TransactionDefinition接口定义了一个事务规则,该接口必须指定如下几个属性值:
⊙ 事务隔离 : 当前事务和其他事务的隔离程度。例如,这个事务能否看到其他事务未提交的数据等。
⊙ 事务传播 : 通常,在事务中执行的代码都会在当前事务中运行。但是,如果一个事务上下文已经存在,有几个选项可指定该事务性方法的执行行为。例如,在大多数情况下,简单地在现有的事务上下文中运行;或者挂起现有事务,创建一个新的事务。Spring提供EJB CMT(Contain Manager Transaction,容器管理事务)中所有的事务传播选项。
⊙ 事务超时 : 事务在超时前能运行多久,也就是事务的最长持续时间。如果事务一直没有被提交或回滚,将在超出该时间后,系统自动回滚事务。
⊙ 只读状态 : 只读事务不修改任何数据。在某些情况下(例如使用Hibernate时),只读事务是非常有用的优化。
TransactionStatus 代表事务本身,它提供了简单的事务执行和查询事务状态的方法,这些方法在所有事务API中都是相同的。
TransactionStatus接口的源代码如下:
package edu.pri.lime._8_6_1.sourcecode; public interface TransactionStatus { // 判断事务是否为新建的事务
boolean isNewTransaction(); // 设置事务回滚
void setRollBackOnly(); // 查询事务是否已有回滚标志
boolean isRollBackOnly();
}
Spring 具体的事务管理由PlatformTransactionManager的不同实现类来完成。在Spring容器中配置PlatformTransactionManger Bean时,必须针对不同的环境提供不同的实现类。
JDBC数据源的局部事务管理器的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 扫描Spring的组件 -->
<context:component-scan base-package="edu.pri.lime._8_6_1.jdbc.service.impl"/> <!-- 定义数据源Bean,使用C3P0数据源实现,并注入数据源的必要信息 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost/spring"/>
<property name="user" value="root"/>
<property name="password" value="System"/>
<property name="maxPoolSize" value="40"/>
<property name="minPoolSize" value="2"/>
<property name="initialPoolSize" value="2"/>
<property name="maxidleTime" value="30"/>
</bean> <!-- 配置JDBC数据源的局部事务管理器,使用DataSourceTransactionManager类 -->
<!-- 该类实现PlatformTransactionManager接口,是针对采用数据源连接的特定实现 -->
<!-- 配置DataSourceTransactionManager时需要依赖注入DataSource的引用 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
容器管理的JTA全局事务管理器的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 扫描Spring的组件 -->
<context:component-scan base-package="edu.pri.lime._8_6_1.jta.service.impl"/> <!-- 配置JNDI数据源Bean,其中jndiName指定容器管理数据源的JNDI -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/jpetstore"/>
</bean> <!-- 使用JtaTransactionManager类,该类实现了PlatformTransactionManager接口 -->
<!-- 针对采用全局事务管理的特定实现 -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> <!-- 当配置JtaTransactionManager全局事务管理策略时,只需指定事务管理器实现类即可,无须传入额外的事务性资源。 -->
<!-- 这是因为全局事务的JTA资源由Java EE服务器提供,而Spring容器能自行从Java EE服务器中获取该事务性资源,所以无须使用依赖注入来配置 -->
</beans>
当采用Hibernate持久层访问策略时,局部事务策略的配置文件如下:
懒的写。留着以后配置成MyBatis
不论采用那种持久层反问技术,只要使用JTA全局事务,Spring事务管理的配置完全一样,因为它们采用的都是全局事务管理策略。
注意:
当采用JTA全局事务策略时,实际上需要底层应用服务器的支持,而不同的应用服务器所提供的JTA全局事务可能存在细节上的差异,因此实际配置全局事务管理器时可能需要使用JtaTransactionManager的子类,如OC4JJtaTransactionManager(Oracle提供的Java EE应用服务器)、WebLogicJtaTransactionManager(Oracle提供的WebLogic)、WebSphereUowTransactionManager(IBM提供的WebSphere)等,它们分别对应于不同的应用服务器。
综合三种配置文件来说,当应用程序采用Spring事务管理策略时,应用程序无须与具体的事务策略耦合,应用程序只要面向PlatformTransactionManager策略接口编程,ApplicationContext将会根据配置文件选择何时的事务策略实现类。
实际上,Spring提供了如下两种事务管理方式:
⊙ 编程式事务管理 : 及时使用Spring的编程式事务,程序也可直接获取容器中的TransactionManager Bean,该Bean忠实PlatformTransactionManager的实例,所以可以通过该接口提供的三个方法来开始事务、提交事务和回滚事务。
⊙ 声明式事务管理 : 无须在Java程序中书写任何事务操作代码,而是通过在XMl文件中为业务组件配置事务代理(AOP代理的一种),AOP为事务代理所织入的增强处理也由Spring提供 ------ 在目标方法执行之前,织入开始事务;在目标方法执行之后,织入结束事务。
不论采用何种持久化策略,Spring都提供了一致的事务抽象,因此,应用开发者能在任何环境下,使用一致的编程模型。无须更改代码,应用就可在不同的事务管理策略中切换。
当使用编程式事务时,开发者使用的是Spring事务抽象(面向PlatformTransactionManager接口编程),而无须使用任何具体的底层事务API。Spring的事务管理将代码从底层具体的事务API中抽象出来,该抽象能以任何底层事务为基础。
提示:
Spring的编程式事务还可通过TransactionTemplate类来完成,该类提供了一个execute(TransactionCallback action)方法,可以以更简捷的方式来进行事务操作。
当使用声明式事务时,开发者无须书写任何事务管理代码,不依赖Spring或任何其他事务API。Spring的声明式事务无须任何额外的容器支持,Spring容器本身管理声明式事务。使用声明式事务策略,可以让开发者更好地专注于业务逻辑的实现。
注意:
Spring 所支持的事务策略非常灵活,Spring的事务策略允许应用程序在不同的事务策略之间自由切换,及时需要在局部事务策略和全局事务策略之间切换,也只需修改配置文件即可,而应用程序的代码无须任何改变。这种灵活的设计,正是面向接口编程带来的优势。
啦啦啦
啦啦啦
8 -- 深入使用Spring -- 6...1 Spring支持的事务策略的更多相关文章
- 8 -- 深入使用Spring -- 6...2 Spring支持的事务策略
8.6.2 使用XML Schema配置事务策略 Spring 同时支持编程式事务策略和声明式事务策略,通常都推荐采用声明式事务策略. ⊙ 声明式事务能大大降低开发者的代码书写量,而且声明式事务几乎不 ...
- 8.Spring对JDBC的支持和事务
1.Spring对JDBC的支持 DAO : Spring中对数据访问对象(DAO)的支持旨在简化Spring与数据访问技术的操作,使JDBC.Hibernate.JPA和JDO等采用统一的方式访问 ...
- java 利用spring JavaMailSenderImpl发送邮件,支持普通文本、附件、html、velocity模板
java 利用spring JavaMailSenderImpl发送邮件,支持普通文本.附件.html.velocity模板 博客分类: Java Spring 本文主要介绍利用JavaMailS ...
- Spring AOP和AspectJ支持
学了Spring之后发现我都不知道java为何物-- 在这一章中有好几节,讲的切面编程 第一节:在项目中启用Spring的AspectJ注解支持 第二节:用AspectJ注解声明aspect 第三节: ...
- Spring使用拦截器支持国际化(转)
Spring使用拦截器支持国际化很方便,使用时只需要两个步骤: 一.spring配置 具体配置方式如下: <!-- 资源文件绑定器,文件名称:messages.properties(没有找到时的 ...
- Spring对远程服务的支持
Java程序有以下的远程调用技术选择: 远程过程调用(RPC)是同步的,客户端在服务器端返回结果之前将一直被阻塞. 各种技术适用的场景如下: 典型的RMI开发的过程如下: 定义一个接口,用于客户端和服 ...
- 1.Spring对JDBC整合支持
1.Spring对JDBC整合支持 Spring对DAO提供哪些支持 1)Spring对DAO异常提供统一处理 2)Spring对DAO编写提供支持的抽象类 3)提高编程效率,减少DAO编码量 Spr ...
- [Spring学习笔记 7 ] Spring中的数据库支持 RowMapper,JdbcDaoSupport 和 事务处理Transaction
1.Spring中的数据库支持 把具有相同功能的代码模板抽取到一个工具类中.2.关于jdbc template的应用 jdbcTemplate模板操作类,把访问jdbc的模板抽取到template中, ...
- Spring Boot 添加JSP支持【转】
Spring Boot 添加JSP支持 大体步骤: (1) 创建Maven web project: (2) 在pom.xml文件添加依赖: (3) ...
随机推荐
- 在Springboot2.0项目中使用Druid配置多数据源
在Springboot出现之前配置数据源以及相关的事物,缓存等内容一直是个繁琐的工作,但是Springboot出现后这些基本都可以靠默认配置搞定,就变得很轻松了.这就是现在推崇模板>配置的原因, ...
- spring和springMVC的面试问题总结
1.Spring中AOP的应用场景.Aop原理.好处? 答:AOP--Aspect Oriented Programming面向切面编程:用来封装横切关注点,具体可以在下面的场景中使用: Authen ...
- __Linux__文件和目录
Linux 目录 /:根目录,一般根目录下只存放目录,在Linux下有且只有一个根目录.所有的东西都是从这里开始.当你在终端里输入“/home”,你其实是在告诉电脑,先从/(根目录)开始,再进入到ho ...
- HTML:Browser 对象
ylbtech-HTML:Browser 对象 1.返回顶部 1. Window 对象 Window 对象表示浏览器中打开的窗口. 如果文档包含框架(frame 或 iframe 标签),浏览器会为 ...
- verilog语法实例学习(12)
verilog中的综合和不可综合总结 Verilog中综合的概念 综合就是EDA工具或者说综合工具把我们编写的verilog代码转化成具体电路的过程.Verilog中有很多语法,结构,过程,语句,有些 ...
- C# 远程服务器 创建、修改、删除 应用程序池 网站
首先 C# 操作 站点 需要 引用Microsoft.Web.Administration.dll 文件,创建站点我们一般需要 远程服务的IP,网站名称.端口.物理路径:这里默认网站名称和应用程序池名 ...
- [leetcode]Largest Rectangle in Histogram @ Python
原题地址:https://oj.leetcode.com/problems/largest-rectangle-in-histogram/ 题意: Given n non-negative integ ...
- wxParse解析富文本内容使点击图片可以选中并实现放大缩小
wxParse解析富文本内容不多说,之前写过步骤介绍,主要是在使用过程中发现解析的富文本内容里有图片时有的可以点击放大缩小,有的点击却报错,找不到imgUrls. 经过排查发现:循环解析的富文本内容正 ...
- 【设计模式】jdbc桥连接过程解析
读多少源码,便知自己有多无知! 想温习一下桥链接模式,然后觉得自己已然吃透了,因为自己写的博客,觉得还是应该更具体一些. 类似于这样的结构: 个人理解: 模式类型:概述:角色:模式的应用场景:结 ...
- 浅谈压缩感知(二十三):压缩感知重构算法之压缩采样匹配追踪(CoSaMP)
主要内容: CoSaMP的算法流程 CoSaMP的MATLAB实现 一维信号的实验与结果 测量数M与重构成功概率关系的实验与结果 一.CoSaMP的算法流程 压缩采样匹配追踪(CompressiveS ...