Spring事务服务
Spring为事务管理提供了一流的支持。同时支持编程式事务和声明式事务。无论是编程式事务,还是声明式事务,在开发Spring应用工程中,开发者都不需要同具体的事务管理实现进行交互。
事务管理抽象是Spring提供的最为重要的一种抽象。秉承Spring的设计原则,对于事务管理而言,Soring的食物抽象具有如下几方面的优势:
● 对于采用手工控制事务,即程序控制事务的编程方式而言,Spring提供的事务抽象易于使用。
● 无论底层的事务API是什么,Spring都能够提供一致的编程模型。
● Spring支持以声明方式管理事务,这其中主要依赖于Spring AOP模块提供的功能。因此,Spring
AOP在Spring事务抽象服务中起了重要作用。
● 能够同Spring的DAO抽象进行集成。
● 在不同事务服务之间切换,只会涉及到Spring配置文件的修改,而不会涉及到代码的修改。
数据库事务
通常,数据库事务都具备ACID的特性。
●
A,即原子性(Atomicity)。表示组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有的操作成功执行,整个事务才提交,事务中任何一个数据库操作失败,已经执行的任何操作都必须撤销,让数据库返回到初始状态。继而保证事物的原子性。
●
C,即一致性(Consistency)。事务操作将导致一致性的结果,即使得其操作的资源处于一致性状态。无论是事务成功提交,还是回滚,都必须保证资源状态的一致性。当然,这种一致性在很大程度上需要由应用保证,因此C同A、I、D存在很大区别。
●
I,即隔离性(Isolation)。是事务执行过程中,其操作的资源的状态信息不能够被其他事务操作到。因此,不同事务不能够并发对同一数据资源进行读取或写入操作。在对RDBMS操作过程中,为保证隔离性,经常需要对表、列进行锁定操作。
● D即持久性(Durability)。一旦事务成功提交,则事务所导致的结果应该是持久的,即使系统瘫痪都需要保证持久性。
对于声明式事务,Spring支持各种事务管理器,它提供TransactionProxyFactoryBean类,供实现声明式事务使用。
对于编程式事务,Spring也支持各种事务管理器,而且,比声明式事务更灵活。
在Spring提供的所有事务管理器中,PlatformTransactionManager(org.springframework.transaction.PlatformTransactionManager)是最基本的接口也是很重要的接口。
开发者应该很清楚,Spring框架肯定会为它提供若干个实现,供Spring
IOC实现控制反转使用。对于Hiberante,需要借助于 HiberanteTransactionManager
将会把事务处理的具体工作委派给Hiberante中的net.sf.hiberante.Transation对象。其实,Spring提供的所用事务管理器中,都是对底层事务对象的封装。它自身并没有实现底层事务的管理。这也符合Spring的设计初衷——“不重复发明轮子”。对HibernateTransactionManager的commit
和 rollback操作将委派给Transaction对象。
<bean id=”transactionManager”
class=”org.springframework.orm.hibernate.HibernateTransactionManager”>
<property
name=”sessionFactory”>
<ref
local=”sessionFactory”/>
</property>
</bean>
HibernateTransactionManager就是实现PlatformTransactionManager接口,而且还是通过Spring
IoC容器加载的。
Spring主要涉及到的事务管理器有:
●
JDBC事务:借助于DataSourceTransactionManager实现。
●
JTA事务:借助于JtaTransactionManager、WebLogicJtaTransactionManager实现。
●
Hibernate事务:借助于HibernateTransactionManager实现。
●
JDO事务:借助于JdoTransactionManager实现。
●
OJB事务:借助于PersistenceBrokerTransactionManager实现。
●
JMS事务:借助于JmsTransactionManager实现。
对于JDBC事务而言,需要配置DataSourceTransactionManager。配置示例如下。
<bean id=”transactionManager”
class=”org.springframework.jdbc.datasource.DataSourceTransactionManager”>
<property name=”dataSource”>
<ref local=”dataSource”/>
</property>
</bean>
<bran id=”dataSource”
class=”org.springframework.jndi.JndiObjectFactoryBean”>
<property name=”jndiName”>
<value>java:/MySqlDS</value>
</property>
</bean>
开发者需要为它准备dataSource
取值。至于dataSource的具体来源,DataSourceTransactionManager可以不用关注。这或许就是IoC的好处,而且还可以在产品部署场合动态切换。DataSourceTransactionManager会将事务
commit 和 rollback 操作委派给java.sql.Commection。
对于JDO事务而言,需要配置JdoTransactionManager。配置如下:
<bean id=”transactionManager”
class=”org.springframework.orm.jdo.JdoTransactionManager”>
<property
name=”persistenceManagerFactory”>
<ref
local=”persistenceManagerFactory”/>
</property>
</bean>
对于JTA事务而言,需要配置JtaTransactionManager或者WebLogicJtaTransactionManager实现。配置如下:
<bean id=”transactionManager”
class=”org.springframework.transaction.jta.JtaTransactionManager”>
<property
name=”userTransactionName”>
<value>java:comp/UserTransaction</value>
</property>
</bean>
其中,指定了userTransactionName
属性。默认时,JtaTransactionManager设定userTransactionName属性取值为java:comp/UserTransaction,因此如果目标JTA实现的UserTransaction
名为java:comp/UserTransaction,则不用给出userTransactionName属性。当然,除了userTransactionName
属性外,还具有transactionManagerName、jndiTemplate、autodetectTransactionManager、等属性。其中,TransactionManagerName指定事务管理器名字;jndiTemplate
指定JNDI 模版,供查找事务管理器和
UserTransaction对象使用;autodetectTransactionManager用于指定是否自动查找事务管理器(默认时为true)。
声明式事务
借助Spring AOP,Spring提供了
TransactionProxyFactoryBean,它是为简化声明式事务处理而引入的代理工厂
JavaBean。当然,也可以使用ProxyFactoryBean 和
TransactionInterceptor的组合。在TransactionProxyFactoryBean 内部使用了事务拦截器,即
TransactionInterceptor。
使用声明式事务管理器,首先要搭建SSH框架,添加 Spring AOP JAR包,添加方法详见上篇:http://blog.sina.com.cn/s/blog_655974a60101c891.html#bsh-75-262512748
事务配置
首先在/WEB-INF/applicationContext.xml添加以下内容:
<!-- 配置事务管理器
-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="mySessionFactory"/>
</property>
</bean>
注:这是作为公共使用的事务管理器Bean。这个会是事先配置好的,不需各个模块各自去配。
下面就开始配置各个模块所必须的部分,在各自的applicationContext-XXX-beans.xml配置的对于事务管理的详细信息。
首先就是配置事务的传播特性,如下:
<!-- 配置事务传播特性
-->
<tx:advice id="TestAdvice"
transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*"
propagation="REQUIRED"/>
<tx:method name="del*"
propagation="REQUIRED"/>
<tx:method name="update*"
propagation="REQUIRED"/>
<tx:method name="add*"
propagation="REQUIRED"/>
<tx:method name="find*"
propagation="REQUIRED"/>
<tx:method name="get*"
propagation="REQUIRED"/>
<tx:method name="apply*"
propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置参与事务的类
-->
<aop:config>
<aop:pointcut
id="allTestServiceMethod" expression="execution(*
com.test.testAda.test.model.service.*.*(..))"/>
<aop:advisor
pointcut-ref="allTestServiceMethod" advice-ref="TestAdvice"
/>
</aop:config>
事务的几种传播特性
1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3. PROPAGATION_MANDATORY:
如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4. PROPAGATION_REQUIRES_NEW:
总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中.
如果没有活动事务,则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
需要注意的地方:
(1)
advice(建议)的命名:由于每个模块都会有自己的Advice,所以在命名上需要作出规范,初步的构想就是模块名+Advice(只是一种命名规范)。
(2) tx:attribute标签所配置的是作为事务的方法的命名类型。
如<tx:method name="save*"
propagation="REQUIRED"/>
其中*为通配符,即代表以save为开头的所有方法,即表示符合此命名规则的方法作为一个事务。
propagation="REQUIRED"代表支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
(3)
aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。
首先应该特别注意的是id的命名,同样由于每个模块都有自己事务切面,所以我觉得初步的命名规则因为
all+模块名+ServiceMethod。而且每个模块之间不同之处还在于以下一句:
expression="execution(*
com.test.testAda.test.model.service.*.*(..))"
其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数。
(4) aop:advisor标签就是把上面我们所配置的事务管理两部分属性整合起来作为整个事务管理。
图解:

下面给出详细的applicationContext.xml 文件的注释:
<?xml version="1.0"
encoding="gb2312"?>
<!--
Spring配置文件的文件头,包含DTD等信息-->
<!DOCTYPE
beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--定义数据源-->
<bean
id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--
定义数据库驱动-->
<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
<!--
定义数据库url-->
<property name="url"><value>jdbc:mysql://localhost:3306/spring</value></property>
<!--
定义数据库用户名-->
<property name="username"><value>root</value></property>
<!--
定义数据库密码-->
<property name="password"><value>32147</value></property>
</bean>
<!--定义一个hibernate的SessionFactory-->
<bean
id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!--
定义SessionFactory必须注入DataSource-->
<property name="dataSource"><ref
local="dataSource"/></property>
<property name="mappingResources">
<list>
<!--以下用来列出所有的PO映射文件-->
<value>Person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<!--此处用来定义hibernate的SessionFactory的属性:
不同数据库连接,启动时选择create,update,create-drop-->
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop
key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!--
定义事务管理器,使用适用于Hibernte的事务管理器-->
<bean
id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!--
HibernateTransactionManager
bean需要依赖注入一个SessionFactory
bean的引用-->
<property name="sessionFactory"><ref
local="sessionFactory"/></property>
</bean>
<!--定义DAO Bean ,
作为事务代理的目标-->
<bean id="personDaoTarget" class="lee.PersonDaoHibernate">
<!--
为DAO
bean注入SessionFactory引用-->
<property name="sessionFactory"><ref
local="sessionFactory"/></property>
</bean>
<!--
定义DAO
bean的事务代理-->
<bean id="personDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--
为事务代理bean注入事务管理器-->
<property name="transactionManager"><ref
bean="transactionManager"/></property>
<!--
设置事务属性-->
<property
name="transactionAttributes">
<props>
<!--
所有以find开头的方法,采用required的事务策略,并且只读-->
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<!--
其他方法,采用required的事务策略
->
<prop
key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<!--
为事务代理bean设置目标bean
-->
<property
name="target">
<ref
local="personDaoTarget"/>
</property>
</bean>
</beans>
在上面的配置文件中,personDao需要配置两个部分,一个是personDao的目标bean,该目标bean是实际DAO
bean,以实际的DAO bean为目标,建立事务代理。一个组件,需要来个bean组成,一个目标bean,一个事务代理。
这种配置方式还有一个坏处:目标bean直接暴露在Spring容器中,可以直接引用,如果目标bean被误引用,将导致业务操作不具备事务性。
为了避免这种现象,可将目标bean配置成嵌套bean,下面是目标bean和事务代理的配置片段:
<!--
定义DAO
bean的事务代理-->
<bean
id="personDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--
为事务代理bean注入事务管理器-->
<property
name="transactionManager"><ref
bean="transactionManager"/></property>
<!--
设置事务属性-->
<property
name="transactionAttributes">
<props>
<!--
所有以find开头的方法,采用required的事务策略,并且只读-->
<prop
key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<!--
其他方法,采用required的事务策略
->
<prop
key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<!--
为事务代理bean设置目标bean
-->
<property
name="target">
<!--
采用嵌套bean配置目标bean-->
<bean
class="lee.PersonDaoHibernate">
<!--
为DAO
bean注入SessionFactory引用-->
<property name="sessionFactory"><ref
local="sessionFactory"/></property>
</bean>
</property>
</bean>
0
喜欢
0
赠金笔
-->
0
赠金笔
转载列表:
转载
转载是分享博文的一种常用方式...
- 评论加载中,请稍候...
Spring事务服务的更多相关文章
- spring事务管理器设计思想(二)
上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当前没有事务,就新建一个事务.这是最常见 ...
- Spring事务传播属性
Spring 对事务控制的支持统一在 TransactionDefinition 类中描述,该类有以下几个重要的接口方法: int getPropagationBehavior():事务的传播行为 i ...
- Spring 事务管理高级应用难点剖析--转
第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...
- Spring事务传播机制
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播,即协调已经有事务标识的方法之间的发生调用时的事务 ...
- Spring事务传播特性的浅析——事务方法嵌套调用的迷茫
Spring事务传播机制回顾 Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务.结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷. 其实这 ...
- 2015第24周一Spring事务
1. Spring事务管理简介 (1)Spring为多种不同类型的事务管理机制提供统一编程模型,这些事务管理模型包括JTA.JDBC.Hibernate.JPA和JDO. (2)Spring支持声明式 ...
- spring事务管理器设计思想(2)
spring事务管理器设计思想(二) 上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当 ...
- spring事务探索
spring自建事务管理模块.而且这个事务管理是一个抽象设计,可以应用到很多场合,包括普通的DataSource,jta,jms和hibernate上. 要正确使用spring的事务,首先需要了解s ...
- Spring事务事件监控
前面我们讲到了Spring在进行事务逻辑织入的时候,无论是事务开始,提交或者回滚,都会触发相应的事务事件.本文首先会使用实例进行讲解Spring事务事件是如何使用的,然后会讲解这种使用方式的实现原理. ...
随机推荐
- pair node stack vector string priority_queue
multiset 元素重复 自动排序 map #include <bits/stdc++.h> using namespace std; map<int,int> s;//自当 ...
- WLC-生成CSR操作
1.生成CSR [req]req_extensions = v3_req[ v3_req ]# Extensions to add to a certificate requestbasicConst ...
- express 应用创建及app.js详解
#1 express 应用创建 1.安装node.js (自行百度) 2.npm install express -g 3.全局安装express生成器 express-generator npm i ...
- vs2013设置不生成.sdf和ipch文件
转载:https://blog.csdn.net/sinat_23338865/article/details/53393760 使用VS2013建立解决方案时,会生成SolutionName.sdf ...
- 小白学 Python 爬虫:Selenium 获取某大型电商网站商品信息
目标 先介绍下我们本篇文章的目标,如图: 本篇文章计划获取商品的一些基本信息,如名称.商店.价格.是否自营.图片路径等等. 准备 首先要确认自己本地已经安装好了 Selenium 包括 Chrome ...
- cross_val_score 交叉验证与 K折交叉验证,嗯都是抄来的,自己作个参考
因为sklearn cross_val_score 交叉验证,这个函数没有洗牌功能,添加K 折交叉验证,可以用来选择模型,也可以用来选择特征 sklearn.model_selection.cross ...
- SpringMVC:详述拦截器
将堆内存SpringMVC使用拦截器对请求进行拦截处理,以实现特定的功能: 具体实现: 1.自定义一个实现HandlerInterceptor接口的类并实现接口中定义的抽象方法(实现了三个方法,分别处 ...
- Hibernate框架报错:org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.mikey.hibernate.domain.Person.pid
报错信息 org nate.PropertyAccessException:IllegalArgumentException在调用com.mikey.Hibernate.domain.Person.p ...
- CSS概述(最详细!!!)
一.先综述 二.分述: 1.简介: 2.基本用法 3.引入方式: 4.盒模型 5.选择器: 6.常见文本样式及复合样式 7.改变行.块元素的属性: 8.标签显示与隐藏: ...
- Microsoft Cortana移动版除美国市场外不再可用
导读 先前已经透露,Microsoft Cortana的移动版本已不复存在.目前,Microsoft Cortana在移动设备上的多个国家和地区中支持多种语言.微软的Cortana移动版本不再支持的市 ...













