全面分析 Spring 的编程式事务管理及声明式事务管理
spring事务配置的五种方式

Spring事务配置的五种方式前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识。
通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的。
总结如下:Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
具体如下图:根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:第一种方式:每个Bean都有一个代理<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/conte xt"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/ beans/schema/beans/spring-bea ns-2.5.xsd/schema/context/schema/context/spring-co ntext-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionF actoryBean"><property name="configLocation"value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransac tionManager"><property name="sessionFactory" ref="sessionFactory"/> </bean><!-- 配置DAO --><bean id="userDaoTarget"class="erDaoImpl"><property name="sessionFactory" ref="sessionFactory"/> </bean><bean id="userDao"class="org.springframework.transaction.interceptor.Transactio nProxyFactoryBean"><!-- 配置事务管理器--><property name="transactionManager"ref="transactionManager"/><property name="target" ref="userDaoTarget"/><property name="proxyInterfaces"value="com.bluesky.spring.dao.GeneratorDao"/><!-- 配置事务属性--><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop> </props></property></bean></beans>第二种方式:所有Bean共享一个代理基类<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/conte xt"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/ beans/schema/beans/spring-bea ns-2.5.xsd/schema/context/schema/context/spring-co ntext-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionF actoryBean"><property name="configLocation"value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/> </bean><bean id="transactionBase"class="org.springframework.transaction.interceptor.Transa ctionProxyFactoryBean"lazy-init="true" abstract="true"><!-- 配置事务管理器--><property name="transactionManager"ref="transactionManager"/><!-- 配置事务属性--><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop> </props></property></bean><!-- 配置DAO --><bean id="userDaoTarget"class="erDaoImpl"><property name="sessionFactory" ref="sessionFactory"/> </bean><bean id="userDao" parent="transactionBase"><property name="target" ref="userDaoTarget"/> </bean></beans>第三种方式:使用拦截器<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/conte xt"xmlns:aop="/schema/aop"xsi:schemaLocation="/schema/ beans/schema/beans/spring-bea ns-2.5.xsd/schema/context/schema/context/spring-co ntext-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd"><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionF actoryBean"><property name="configLocation"value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager"><property name="sessionFactory" ref="sessionFactory"/> </bean><bean id="transactionInterceptor"class="org.springframework.transaction.interceptor.Transactio nInterceptor"><property name="transactionManager"ref="transactionManager"/><!-- 配置事务属性--><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop> </props></property></bean><beanclass="org.springframework.aop.framework.autoproxy.BeanNameA utoProxyCreator"><property name="beanNames"><list><value>*Dao</value></list></property><property name="interceptorNames"><list><value>transactionInterceptor</value></list></property></bean><!-- 配置DAO --><bean id="userDao"class="erDaoImpl"><property name="sessionFactory" ref="sessionFactory"/> </bean></beans>第四种方式:使用tx标签配置的拦截器<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/conte xt"xmlns:aop="/schema/aop"xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/ beans/schema/beans/spring-bea ns-2.5.xsd/schema/context/schema/context/spring-co ntext-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd /schema/tx/schema/tx/spring-tx-2.5.xsd"><context:annotation-config/><context:component-scan base-package="com.bluesky"/><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionF actoryBean"><property name="configLocation"value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransac tionManager"><property name="sessionFactory" ref="sessionFactory"/> </bean><tx:advice id="txAdvice"transaction-manager="transactionManager"><tx:attributes><tx:method name="*" propagation="REQUIRED"/> </tx:attributes></tx:advice><aop:config><aop:pointcut id="interceptorPointCuts"expression="execution(* com.bluesky.spring.dao.*.*(..))"/> <aop:advisor advice-ref="txAdvice"pointcut-ref="interceptorPointCuts"/></aop:config></beans>第五种方式:全注解<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/conte xt"xmlns:aop="/schema/aop"xmlns:tx="/schema/tx"xsi:schemaLocation="/schema/ beans/schema/beans/spring-bea ns-2.5.xsd/schema/context/schema/context/spring-co ntext-2.5.xsd/schema/aop/schema/aop/spring-aop-2.5.xsd /schema/tx/schema/tx/spring-tx-2.5.xsd"><context:annotation-config/><context:component-scan base-package="com.bluesky"/><tx:annotation-driven transaction-manager="transactionManager "/><bean id="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionF actoryBean"><property name="configLocation"value="classpath:hibernate.cfg.xml"/><property name="configurationClass"value="org.hibernate.cfg.AnnotationConfiguration"/></bean><!-- 定义事务管理器(声明式的事务)--><bean id="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransac tionManager"><property name="sessionFactory" ref="sessionFactory"/> </bean></beans>此时在DAO上需加上@Transactional注解,如下:package com.bluesky.spring.dao;import java.util.List;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import ponent;import er;@Transactional@Component("userDao")public class UserDaoImpl extends HibernateDaoSupport implements Us erDao {public List<User>listUsers() {return this.getSession().createQuery("from User").list();}}。
全面分析Spring的编程式事务管理及声明式事务管理

开始之前关于本教程本教程将深入讲解Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务。
通过对本教程的学习,您将能够理解Spring 事务管理的本质,并灵活运用之。
先决条件本教程假定您已经掌握了Java 基础知识,并对Spring 有一定了解。
您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等。
本文将直接使用这些概念而不做详细解释。
另外,您最好掌握数据库的基础知识,虽然这不是必须。
系统需求要试验这份教程中的工具和示例,硬件配置需求为:至少带有512MB 内存(推荐1GB)的系统。
需要安装以下软件:•Sun JDK 5.0 或更新版本或IBM Developer Kit for the Java 5 platform 版本。
•Spring framework 2.5。
本教程附带的示例代码已经在Spring 2.5.6 上测试过。
•MySQL 5.0 或更新版本。
Spring 事务属性分析事务管理对于企业应用而言至关重要。
它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。
就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保证用户和银行的利益都不受损失。
在Spring 中,事务是通过TransactionDefinition 接口来定义的。
该接口包含与事务属性有关的方法。
具体如清单1所示:清单1. TransactionDefinition 接口中定义的主要方法public interface TransactionDefinition{int getIsolationLevel();int getPropagationBehavior();int getTimeout();boolean isReadOnly();}也许你会奇怪,为什么接口只提供了获取属性的方法,而没有提供相关设置属性的方法。
Spring事务配置的五种方式

Spring事务原理统观spring事务,围绕着两个核心PlatformTransactionManager和TransactionStatusspring提供了几个关于事务处理的类:TransactionDefinition //事务属性定义TranscationStatus //代表了当前的事务,可以提交,回滚。
PlatformTransactionManager这个是spring提供的用于管理事务的基础接口,其下有一个实现的抽象类AbstractPlatformTransactionManager,我们使用的事务管理类例如DataSourceTransactionManager等都是这个类的子类。
一般事务定义步骤:TransactionDefinition td = new TransactionDefinition();TransactionStatus ts = transactionManager.getTransaction(td);try{ //do sthmit(ts);}catch(Exception e){transactionManager.rollback(ts);}spring提供的事务管理可以分为两类:编程式的和声明式的。
编程式的,比较灵活,但是代码量大,存在重复的代码比较多;声明式的比编程式的更灵活。
编程式主要使用transactionTemplate。
省略了部分的提交,回滚,一系列的事务对象定义,需注入事务管理对象.void add(){transactionTemplate.execute( new TransactionCallback(){pulic Object doInTransaction(TransactionStatus ts){ //do sth}}}声明式:使用TransactionProxyFactoryBean:<bean id="userManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><property name="transactionManager"><ref bean="transactionManager"/></property><property name="target"><ref local="userManagerTarget"/></property><property name="transactionAttributes"><props><prop key="insert*">PROPAGATION_REQUIRED</prop><prop key="update*">PROPAGATION_REQUIRED</prop><prop key="*">PROPAGATION_REQUIRED,readOnly</prop></props></property></bean>围绕Poxy的动态代理能够自动的提交和回滚事务org.springframework.transaction.interceptor.TransactionProxyFactoryBeanPROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。
Spring编程式事务详解

Spring编程式事务详解为了更细粒度的事务划分,Spring提供如下两种⽅式的编程式事务管理:1 PlatformTransactionManager你也可以使⽤ org.springframework.transaction.PlatformTransactionManager 来直接管理你的事务。
只需通过bean的引⽤,简单的把你在使⽤的PlatformTransactionManager 传递给你的bean。
然后,使⽤TransactionDefinition和TransactionStatus对象, 你可以启动,回滚和提交事务。
DefaultTransactionDefinition def =new DefaultTransactionDefinition();// explicitly setting the transaction name is something that can only be done programmaticallydef.setName("SomeTxName");def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status = txManager.getTransaction(def);try{// 执⾏业务逻辑}catch(MyException ex){txManager.rollback(status);throw ex;}mit(status);2 TransactionTemplatePlatformTransactionManager中部分代码是可以重⽤的,所以spring对其进⾏了优化,采⽤模板⽅法模式就其进⾏封装,主要省去了提交或者回滚事务的代码。
若你选择编程式事务管理,Spring推荐使⽤ TransactionTemplate。
springboot中的声明式事务管理及编程式事务管理

springboot中的声明式事务管理及编程式事务管理这⼏天在做⼀个功能,具体的情况是这样的: 项⽬中原有的⼏个功能模块中有数据上报的功能,现在需要在这⼏个功能模块的上报之后⽣成⼀条消息记录,然后⼊库,在写个接⼝供前台来拉取消息记录。
看到这个需求,⾸先想到的是使⽤AOP来实现了,然后,我去看了下现有功能模块中的代码,发现了问题,这些模块中的业务逻辑并没有放在service层来处理,直接在controller中处理了,controller中包含了两个甚⾄多个service处理,这样是不能保证事务安全的,既然这样,那么我们如何实现能保证事务安全呢。
我想直接在controller中定义切⼊点,然后before中⼿动开启事务,在afterReturn之后根据需要来提交或者回滚事务。
然后趁着这个机会就查了下spring boot中的事务这块,就从最基础的说起。
1.spring boot中声明式事务的使⽤ 想要在spring boot中使⽤声明式事务,有两种⽅式,⼀种是在各个service层中添加注解,还有⼀种是使⽤AOP配置全局的声明式事务管理 先来说第⼀种,需要⽤到两个注解就,⼀个是@EnableTransactionManagement⽤来开启注解事务管理,等同于xml配置⽅式的 <tx:annotation-driven />,另⼀个是@Transactional 具体代码如下:1package com.example.demo;23import org.springframework.boot.SpringApplication;4import org.springframework.boot.autoconfigure.SpringBootApplication;5import org.springframework.transaction.annotation.EnableTransactionManagement;67// @SpringBootApplication是Sprnig Boot项⽬的核⼼注解,主要⽬的是开启⾃动配置10 @SpringBootApplication11 @EnableTransactionManagement // 启注解事务管理,等同于xml配置⽅式的 <tx:annotation-driven />12public class DemoApplication {14public static void main(String[] args) {16 SpringApplication.run(DemoApplication.class, args);18 }1920 } 然后,注解@Transactional直接加在service层就可以了,放两个service⽤来验证事务是否按预期回滚package com.example.demo.service;import com.example.demo.bean.ResUser;import org.springframework.transaction.annotation.Transactional;import java.util.List;/*** 注解加在接⼝上表名接⼝的所有⽅法都⽀持事务;* 如果加在⽅法上,则只有该⽅法⽀持事务* 可以根据需要在CUD操作上加注解**/@Transactionalpublic interface IUserService {int insertUser(ResUser resUser);int updateUser(ResUser resUser);List<ResUser> getResUserList();}1package com.example.demo.service;23import com.example.demo.bean.ResPartner;4import org.springframework.transaction.annotation.Transactional;56import java.util.List;7import java.util.Map;89 @Transactional10public interface IPartnerService {1112int add(ResPartner resPartner);1314int deleteByIds(String ids);1516int update(ResPartner resPartner);1718 ResPartner queryById(int id);1920 List<ResPartner> queryList(Map<String, Object> params);2122 } 实现类1package com.example.demo.service.impl;23import com.example.demo.bean.ResPartner;4import com.example.demo.dao.PartnerMapperXml;5import com.example.demo.service.IPartnerService;6import org.slf4j.Logger;7import org.slf4j.LoggerFactory;8import org.springframework.beans.factory.annotation.Autowired;9import ponent;1011import java.util.List;12import java.util.Map;1314 @Component("partnerService")15public class PartnerServiceImpl implements IPartnerService {1617private Logger logger = LoggerFactory.getLogger(this.getClass());18 @Autowired19private PartnerMapperXml partnerMapperXml;2021 @Override22public int add(ResPartner resPartner) {23 StringBuilder sbStr = new StringBuilder();24 sbStr.append("id = ").append(resPartner.getId())25 .append(", name = ").append(resPartner.getName())26 .append(", city = ").append(resPartner.getCity())27 .append(", displayName = ").append(resPartner.getDisplayName());(sbStr.toString());29return this.partnerMapperXml.add(resPartner);30 }31 }1package com.example.demo.service.impl;23import com.example.demo.bean.ResPartner;4import com.example.demo.bean.ResUser;5import com.example.demo.dao.PartnerMapperXml;6import com.example.demo.dao.ResUserMapper;7import com.example.demo.service.IUserService;8import org.springframework.beans.factory.annotation.Autowired;9import ponent;1011import java.util.List;1213 @Component("userService")14public class UserServiceImpl implements IUserService {1516 @Autowired17private ResUserMapper resUserMapper;18 @Autowired19private PartnerMapperXml partnerMapperXml;2021 @Override22public int insertUser(ResUser resUser) {2324int i = resUserMapper.insert(resUser);25// ResPartner partner = new ResPartner();26// partner.setId(resUser.getId());27// partner.setName(resUser.getName());28// partner.setDisplayName(resUser.getLogin());29//30// if (true) // ⽤来验证异常,使事务回滚31// throw new RuntimeException("xxxxxxxxxxxxxxx");32// int a = 1/0;33// partnerMapperXml.add(partner);3435return i;36 }3738 } controller代码,JSONMsg是⼀个⾃定义类,就三个属性code,msg,data⽤来给前台返回数据。
J2EE项目实训 Spring框架技术——第9章 Spring中的事务管理技术及实现(第3部分)

第9章Spring中的事务管理技术及实现(第3/3部分)1.1.1采用TransactionTemplate类简化事务编程实现操作1、TransactionTemplate模板类TransactionTemplate模板类封装了事务管理的功能,这包括产生数据访问异常时的事务回滚,以及操作成功后的事务提交等。
和Spring 框架DAO组件中的JdbcTemplate类一样,它使得开发者无需再关注数据访问中的各种异常出现时的try/catch/finally等代码,这样也将能够帮助开发者省去了部分事务提交、回滚代码。
2、应用TransactionTemplate模板类对前面的DAO类中的doUpdateUserInfo方法进行简化(1)修改原来的DAOImple类中的doUpdateUserInfo方法为下面的【例9-19】中所示的状态由于TransactionTemplate模板类需要采用Java中的内部类的编程风格,为了能够在内部类中访问上层类中的成员数据,将原来在updateOneUserInfo方法中定义的一些参数(请参考【例9-17】中的代码示例)移出到类中进行定义。
并请注意其中的黑体部分的代码。
【例9-19】应用TransactionTemplate模板类的代码示例Object parameter[]=new Object[3];String updateSQL1 =null;String updateSQL2 =null;public boolean updateOneUserInfo(UserInfoVO oneUserInfoVO,String newUserPassWord){String userName=oneUserInfoVO.getUserName();String userPassWord=oneUserInfoVO.getUserPassWord();parameter[0]=newUserPassWord;parameter[1]=userName;parameter[2]=userPassWord;updateSQL1 ="update userInfo set userPassWord = ? where userName =? and userPassWord=?";updateSQL2 ="update abcTable set userPassWord = ? where userName =? and userPassWord=?";TransactionTemplate transactionTemplate =new TransactionTemplate(transactionManager);transactionTemplate.execute(new TransactionCallbackWithoutResult(){public void doInTransactionWithoutResult(TransactionStatus status) {jdbcTemplate.update(updateSQL1,parameter);jdbcTemplate.update(updateSQL2,parameter);}});return true;}(2)对比【例9-19】和【例9-16】中有关事务控制方面的代码明显地能够发现出,应用TransactionTemplate模板类能够简化对事务控制方面的代码实现。
spring事务

Spring事务管理(详解+实例)1 初步理解理解事务之前,先讲一个你日常生活中最常干的事:取钱。
比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱;然后ATM出1000元钱。
这两个步骤必须是要么都执行要么都不执行。
如果银行卡扣除了1000块但是ATM出钱失败的话,你将会损失1000元;如果银行卡扣钱失败但是ATM却出了1000块,那么银行将损失1000元。
所以,如果一个步骤成功另一个步骤失败对双方都不是好事,如果不管哪一个步骤失败了以后,整个取钱过程都能回滚,也就是完全取消所有操作的话,这对双方都是极好的。
事务就是用来解决类似问题的。
事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。
在企业级应用程序开发中,事务管理必不可少的技术,用来确保数据的完整性和一致性。
事务有四个特性:ACID∙原子性(Atomicity):事务是一个原子操作,由一系列动作组成。
事务的原子性确保动作要么全部完成,要么完全不起作用。
∙一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。
在现实中的数据不应该被破坏。
∙隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
∙持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。
通常情况下,事务的结果被写到持久化存储器中。
2 核心接口Spring事务管理的实现有许多细节,如果对整个接口框架有个大体了解会非常有利于我们理解事务,下面通过讲解Spring的事务接口来了解Spring实现事务的具体策略。
Spring事务管理涉及的接口的联系如下:2.1 事务管理器Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
Spring中的事务管理实例详解

Spring中的事务管理实例详解本文实例讲述了Spring中的事务管理。
分享给大家供大家参考。
具体分析如下:事务简介:事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性事务就是一系列的动作,它们被当作一个单独的工作单元。
这些动作要么全部完成,要么全部不起作用事务的四个关键属性(ACID)①原子性(atomicity):事务室一个原子操作,有一系列动作组成。
事务的原子性确保动作要么全部完成,要么完全不起作用②一致性(consistency):一旦所有事务动作完成,事务就被提交。
数据和资源就处于一种满足业务规则的一致性状态中③隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏④持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。
通常情况下,事务的结果被写到持久化存储器中Spring中的事务管理作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层。
而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制。
Spring既支持编程式事务管理,也支持声明式的事务管理编程式事务管理:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码声明式事务管理:大多数情况下比编程式事务管理更好用。
它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
事务管理作为一种横切关注点,可以通过AOP方法模块化。
Spring通过Spring AOP框架支持声明式事务管理。
Spring事务的传播属性:当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。
例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
事务的传播行为可以由传播属性指定。
Spring定义了7种传播行为:Spring支持的事务传播行为传播行为含义PROPAGATION_MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常PROPAGATION_NESTED 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
开始之前关于本教程本教程将深入讲解Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务。
通过对本教程的学习,您将能够理解Spring 事务管理的本质,并灵活运用之。
先决条件本教程假定您已经掌握了Java 基础知识,并对Spring 有一定了解。
您还需要具备基本的事务管理的知识,比如:事务的定义,隔离级别的概念,等等。
本文将直接使用这些概念而不做详细解释。
另外,您最好掌握数据库的基础知识,虽然这不是必须。
系统需求要试验这份教程中的工具和示例,硬件配置需求为:至少带有512MB 内存(推荐1GB)的系统。
需要安装以下软件:•Sun JDK 或更新版本或IBM Developer Kit for the Java 5 platform 版本。
•Spring framework 。
本教程附带的示例代码已经在Spring 上测试过。
•MySQL 或更新版本。
•Spring 事务属性分析事务管理对于企业应用而言至关重要。
它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。
就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作过程中机器突然出故障的情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过取款机一样,以保证用户和银行的利益都不受损失。
在Spring 中,事务是通过TransactionDefinition 接口来定义的。
该接口包含与事务属性有关的方法。
具体如清单1所示:清单1. TransactionDefinition 接口中定义的主要方法public interface TransactionDefinition{int getIsolationLevel();int getPropagationBehavior();int getTimeout();boolean isReadOnly();}也许你会奇怪,为什么接口只提供了获取属性的方法,而没有提供相关设置属性的方法。
其实道理很简单,事务属性的设置完全是程序员控制的,因此程序员可以自定义任何设置属性的方法,而且保存属性的字段也没有任何要求。
唯一的要求的是,Spring 进行事务操作的时候,通过调用以上接口提供的方法必须能够返回事务相关的属性取值。
事务隔离级别隔离级别是指若干个并发的事务之间的隔离程度。
TransactionDefinition 接口中定义了五个表示隔离级别的常量:•:这是默认值,表示使用底层数据库的默认隔离级别。
对大部分数据库而言,通常这值就是。
••:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。
该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
••:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。
该级别可以防止脏读,这也是大多数情况下的推荐值。
••:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。
即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。
该级别可以防止脏读和不可重复读。
••:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
但是这将严重影响程序的性能。
通常情况下也不会用到该级别。
•事务传播行为所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。
在TransactionDefinition定义中包括了如下几个表示传播行为的常量:•:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
••:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
••:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
••:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
••:以非事务方式运行,如果当前存在事务,则抛出异常。
••:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
••:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于。
这里需要指出的是,前面的六种事务传播行为是Spring 从EJB 中引入的,他们共享相同的概念。
而PROPAGATION_NESTED是Spring 所特有的。
以PROPAGATION_NESTED 启动的事务内嵌于外部事务中(如果存在外部事务的话),此时,内嵌事务并不是一个独立的事务,它依赖于外部事务的存在,只有通过外部的事务提交,才能引起内部事务的提交,嵌套的子事务不能单独提交。
如果熟悉JDBC 中的保存点(SavePoint)的概念,那嵌套事务就很容易理解了,其实嵌套的子事务就是保存点的一个应用,一个事务中可以包括多个保存点,每一个嵌套子事务。
另外,外部事务的回滚也会导致嵌套子事务的回滚。
事务超时所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。
在TransactionDefinition 中以int 的值来表示超时时间,其单位是秒。
事务的只读属性事务的只读属性是指,对事务性资源进行只读操作或者是读写操作。
所谓事务性资源就是指那些被事务管理的资源,比如数据源、JMS 资源,以及自定义的事务性资源等等。
如果确定只对事务性资源进行只读操作,那么我们可以将事务标志为只读的,以提高事务处理的性能。
在TransactionDefinition 中以boolean 类型来表示该事务是否只读。
事务的回滚规则通常情况下,如果在事务中抛出了未检查异常(继承自RuntimeException 的异常),则默认将回滚事务。
如果没有抛出任何异常,或者抛出了已检查异常,则仍然提交事务。
这通常也是大多数开发者希望的处理方式,也是EJB 中的默认处理方式。
但是,我们可以根据需要人为控制事务在抛出某些未检查异常时任然提交事务,或者在抛出某些已检查异常时回滚事务。
Spring 事务管理API 分析Spring 框架中,涉及到事务管理的API 大约有100个左右,其中最重要的有三个:TransactionDefinition、PlatformTransactionManager、TransactionStatus。
所谓事务管理,其实就是“按照给定的事务规则来执行提交或者回滚操作”。
“给定的事务规则”就是用TransactionDefinition 表示的,“按照……来执行提交或者回滚操作”便是用PlatformTransactionManager 来表示,而TransactionStatus 用于表示一个运行着的事务的状态。
打一个不恰当的比喻,TransactionDefinition 与TransactionStatus 的关系就像程序和进程的关系。
TransactionDef...该接口在前面已经介绍过,它用于定义一个事务。
它包含了事务的静态属性,比如:事务传播行为、超时时间等等。
Spring 为我们提供了一个默认的实现类:DefaultTransactionDefinition,该类适用于大多数情况。
如果该类不能满足需求,可以通过实现TransactionDefinition 接口来实现自己的事务定义。
PlatformTrans...PlatformTransactionManager 用于执行具体的事务操作。
接口定义如清单2所示:清单2. PlatformTransactionManager 接口中定义的主要方法Public interface PlatformTransactionManager{?TransactionStatus getTransaction(TransactionDefinition definition) ? throws TransactionException;? void commit(TransactionStatus status)throws TransactionException;? void rollback(TransactionStatus status)throwsTransactionException;}根据底层所使用的不同的持久化API 或框架,PlatformTransactionManager 的主要实现类大致如下:•DataSourceTransactionManager:适用于使用JDBC和iBatis进行数据持久化操作的情况。
••HibernateTransactionManager:适用于使用Hibernate进行数据持久化操作的情况。
••JpaTransactionManager:适用于使用JPA进行数据持久化操作的情况。
••另外还有JtaTransactionManager 、JdoTransactionManager、JmsTransactionManager等等。
如果我们使用JTA进行事务管理,我们可以通过JNDI 和Spring 的JtaTransactionManager 来获取一个容器管理的DataSource。
JtaTransactionManager 不需要知道DataSource 和其他特定的资源,因为它将使用容器提供的全局事务管理。
而对于其他事务管理器,比如DataSourceTransactionManager,在定义时需要提供底层的数据源作为其属性,也就是DataSource。
与HibernateTransactionManager 对应的是SessionFactory,与JpaTransactionManager 对应的是EntityManagerFactory 等等。
TransactionStatus(…) 方法返回一个TransactionStatus 对象。
返回的TransactionStatus 对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事务)。
TransactionStatus 接口提供了一个简单的控制事务执行和查询事务状态的方法。
该接口定义如清单3所示:清单3. TransactionStatus 接口中定义的主要方法public ?interface TransactionStatus{? boolean isNewTransaction();? void setRollbackOnly();? boolean isRollbackOnly();}编程式事务管理Spring 的编程式事务管理概述在Spring 出现以前,编程式事务管理对基于POJO 的应用来说是唯一选择。
用过Hibernate 的人都知道,我们需要在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。