spring事务管理
Spring事务管理中@Transactional的参数配置
Spring事务管理中@Transactional的参数配置Spring作为低侵⼊的Java EE框架之⼀,能够很好地与其他框架进⾏整合,其中Spring与Hibernate的整合实现的事务管理是常⽤的⼀种功能。
所谓事务,就必须具备ACID特性,即原⼦性、⼀致性、隔离性和持久性,在Hibernate的实现中,需要我们编写代码来完成事务的控制⼯作。
未使⽤Spring的事务管理12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public static void main(String[] args) {// Configuration cfg = new Configuration();// cfg.configure();// SessionFactory sf = cfg.buildSessionFactory();//因为在HibernateUtil类中已经有⼀部分封装⼯作,所以以上三⾏注释掉了。
Session s = null;Transaction tx = null;try{Class.forName("com.HibernateUtil");s = HibernateUtil.getSession();tx = s.beginTransaction(); //这⾥开启了事务//事务中所需的⼀系列数据库操作。
mit();} catch(HibernateException e) { //如果出现异常,且事务已经开启,则需要回滚。
if(tx != null)tx.rollback();throw e;} catch(ClassNotFoundException e) {e.printStackTrace();} finally{ //⽆论如何都需要关闭Session。
spring成神之路第四十六篇:Spring如何管理多数据源事务?
spring成神之路第四⼗六篇:Spring如何管理多数据源事务?本篇内容:通过原理和⼤量案例带⼤家吃透Spring多数据源事务。
Spring中通过事务管理器来控制事务,每个数据源都需要指定⼀个事务管理器,如果我们的项⽬中需要操作多个数据库,那么需要我们配置多个数据源,也就需要配置多个数据管理器。
多数据源事务使⽤2个步骤1、为每个数据源定义⼀个事务管理器如下⾯代码,有2个数据源分别连接数据库ds1和ds2,然后为每个数据源定义了1个事务管理器,此时spring容器中有2个数据源和2个事务管理器。
//数据源1@Beanpublic DataSource dataSource1() {org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/ds1?characterEncoding=UTF-8");dataSource.setUsername("root");dataSource.setPassword("root123");dataSource.setInitialSize(5);return dataSource;}//事务管理器1,对应数据源1@Beanpublic PlatformTransactionManager transactionManager1(@Qualifier("dataSource1")DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}//数据源2@Beanpublic DataSource dataSource2() {org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/ds2?characterEncoding=UTF-8");dataSource.setUsername("root");dataSource.setPassword("root123");dataSource.setInitialSize(5);return dataSource;}//事务管理器2,对应数据源2@Beanpublic PlatformTransactionManager transactionManager2(@Qualifier("dataSource2")DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}2、指定事务的管理器bean名称使⽤@Transaction中时,需通过@Transaction注解的value或transactionManager属性指定事务管理器bean名称,如:@Transactional(transactionManager ="transactionManager1", propagation =Propagation.REQUIRED)publicvoid required(String name){this.jdbcTemplate1.update("insert into user1(name) VALUES (?)", name);这⾥补充⼀下,之前我们使⽤@Transactional的时候,并没有通过value或者transactionManager设置事务管理器,这是为什么?这是因为我们在spring容器中只定义了⼀个事务管理器,spring启动事务的时候,默认会按类型在容器中查找事务管理器,刚好容器中只有⼀个,就拿过来⽤了,如果有多个的时候,如果你不指定,spring是不知道具体要⽤哪个事务管理器的。
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. 数据库事务支持:Spring事务的实现依赖于数据库的事务功能。
通常情况下,数据库支持ACID(原子性、一致性、隔离性和持久性)事务特性,可以通过SQL的BEGIN、COMMIT 和ROLLBACK等命令来控制事务的开始、提交和回滚操作。
2. 事务管理器:Spring框架提供了事务管理器(TransactionManager)接口,用于管理事务的开始、提交和回滚等操作。
事务管理器可以根据配置信息选择不同的实现,如使用JDBC事务管理器(DataSourceTransactionManager)或者JTA事务管理器(JtaTransactionManager)等。
3. 编程式事务:Spring框架提供了编程式事务管理的支持,通过编写代码显式地控制事务的边界。
开发者可以在代码中使用事务管理器的API来手动管理事务,包括事务的开始、提交和回滚等操作。
这种方式灵活性较高,但也需要开发者手动处理事务的细节。
4. 声明式事务:Spring框架还提供了声明式事务管理的支持,通过使用注解或者XML配置来定义事务的属性和边界。
开发者可以使用@Transactional注解或者事务配置元素来标记方法或者类,指示该方法或者类在执行时需要开启事务。
Spring会在方法调用前后自动地管理事务的开始、提交和回滚等操作。
5. 事务传播行为:Spring事务还支持事务传播行为的定义,即一个方法调用另一个带有事务的方法时事务该如何传播。
例如,当前方法可能会暂停事务、加入到现有的事务中或者创建一个新的事务。
Spring提供了多种事务传播行为的选项,如REQUIRED、REQUIRES_NEW、NESTED等,可以根据需要进行配置。
总的来说,Spring事务的实现原理是通过与数据库或其他存储系统的事务功能结合,通过事务管理器来管理事务的开始、提交和回滚等操作。
spring事务原理
spring事务原理数据库系统内,事务指一系列连续的操作,这系列操作被看作一个整体,要么完全执行,要么完全不执行,不会出现执行部分的情况,这是数据库系统的基本特征之一。
在传统数据库系统中,事务的管理是由数据库系统自身提供的一种功能,然而随着数据库系统的复杂性的增加,数据库中的事务管理越来越复杂,对数据库操作有更多的要求,这样就催生了应用层事务管理技术,而当前最流行的事务管理技术是Spring事务。
Spring事务是一种基于AOP(面向切面编程)的分布式事务管理技术,它能够帮助系统更好的控制事务的处理过程,从而使系统内的数据更加有效率的共享,降低数据库事务的管理复杂度,提高数据库系统的可用性及性能。
Spring事务原理包括几个要素:事务模型、分布式事务处理框架、事务实现机制以及事务管理工具等。
一、事务模型Spring事务原理的核心是事务模型,即它把事务分为两种:提交成功事务和失败事务,在Spring提供的事务模型中,每个事务都只有两种结果,要么提交成功,要么提交失败,而不存在半提交的状态。
在Spring的事务模型中,事务的分类还要求事务的原子性,它要求一旦提交事务,事务就不会再次改变,或者改变的程度会很小。
原子性还表明事务的执行要么完全成功,要么完全失败,不会出现半成功半失败的情况。
二、分布式事务处理框架Spring提供了基于AOP技术的分布式事务处理框架,这种分布式事务处理框架能够有效地支持不同数据库之间的事务处理,它包括三个部分:事务管理器(TransactionManager)、事务拦截器(TransactionInterceptor)和事务事件监听器(TransactionListener)。
事务管理器是Spring对分布式事务的抽象,它可以处理不同类型的事务,它的实现通常会涉及到一些事务拦截器。
事务拦截器是Spring提供的一种安全机制,它能够在事务处理过程中,根据配置的规则,来拦截事务的执行,以便能够在事务处理过程中发现任何可能存在的问题,并对其进行调整,使得事务能够顺利的提交。
spring,mybatis事务管理配置与@Transactional注解使用[转]
spring,mybatis事务管理配置与@Transactional注解使用[转]spring,mybatis事务管理配置与@Transactional注解使用概述事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。
Spring Framework对事务管理提供了一致的抽象,其特点如下:为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用提供比其他事务API如JTA更简单的编程式事务管理API与spring数据访问抽象的完美集成事务管理方式spring支持编程式事务管理和声明式事务管理两种方式。
编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。
对于编程式事务管理,spring推荐使用TransactionTemplate。
声明式事务管理建立在AOP之上的。
其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
显然声明式事务管理要优于编程式事务管理,这正是spring 倡导的非侵入式的开发方式。
声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。
和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
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⽤来给前台返回数据。
MyBatis-Spring-TransactionManager事务管理
</property>
</bean>
编程式事务管理
MyBatis 的 SqlSession 提供指定的方法来处理编程式的事务。 但是当使用 MyBatis-Spring 时, bean 将会使用 Spring 管理的 SqlSession 或映射器来注入。 那就是说 Spring 通常是处理 事务的。
一旦事务创建之后,MyBatis-Spring 将会透明的管理事务。在你的 DAO 类中就不需要额 外的代码了。
标准配置
要 开 启 Spring 的 事 务 处 理 , 在 Spring 的 XML 配 置 文 件 中 简 单 创 建 一 个 DataSourceTransactionManager 对象:
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
</bean>
指定的 DataSource 一般可以是你使用 Spring 的任意 JDBC DataSource。这包含了连接 池和通过 JNDI 查找获得的 DataSource。
要注意, 为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactoryBean 的 是同一个数据源,否则事务管理器就无法工作了。
事务管理的五种方法
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识。
通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的。
总结如下:Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
具体如下图:根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:第一种方式:每个Bean都有一个代理<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/beans"xmlns:xsi="/XMLSchema-instance"xmlns:context="/context"xmlns:aop="/aop"xsi:schemaLocation="/beans/beans/spring-beans-/context/context/spring-context-/aop /aop/spring-aop-"><bean id="sessionFactory"class=""><property name="configLocation"value="classpath:"/><property name="configurationClass"value=""/></bean><!--定义事务管理器(声明式的事务)--><bean id="transactionManager"class=""><property name="sessionFactory"ref="sessionFactory"/> </bean><!--配置DAO--><bean id="userDaoTarget"class=""><property name="sessionFactory"ref="sessionFactory"/> </bean><bean id="userDao"class=""><!--配置事务管理器--><property name="transactionManager"ref="transactionManager"/> <property name="target"ref="userDaoTarget"/><property name="proxyInterfaces"value=""/><!--配置事务属性--><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean></beans>第二种方式:所有Bean共享一个代理基类<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/beans"xmlns:xsi="/XMLSchema-instance"xmlns:context="/context"xmlns:aop="/aop"xsi:schemaLocation="/beans/beans/spring-beans-/context/context/spring-context-/aop /aop/spring-aop-"><bean id="sessionFactory"class=""><property name="configLocation"value="classpath:"/><property name="configurationClass"value=""/></bean><!--定义事务管理器(声明式的事务)--><bean id="transactionManager"class=""><property name="sessionFactory"ref="sessionFactory"/></bean><bean id="transactionBase"class=""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=""><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="/beans"xmlns:xsi="/XMLSchema-instance"xmlns:context="/context"xmlns:aop="/aop"xsi:schemaLocation="/beans/beans/spring-beans-/context/context/spring-context-/aop /aop/spring-aop-"><bean id="sessionFactory"class=""><property name="configLocation"value="classpath:"/><property name="configurationClass"value=""/></bean><!--定义事务管理器(声明式的事务)--><bean id="transactionManager"class=""><property name="sessionFactory"ref="sessionFactory"/></bean><bean id="transactionInterceptor"class=""><property name="transactionManager"ref="transactionManager"/> <!--配置事务属性--><property name="transactionAttributes"><props><prop key="*">PROPAGATION_REQUIRED</prop></props></property></bean><bean class=""><property name="beanNames"><list><value>*Dao</value></list></property><property name="interceptorNames"><list><value>transactionInterceptor</value></list></property></bean><!--配置DAO--><bean id="userDao"class=""><property name="sessionFactory"ref="sessionFactory"/> </bean></beans>第四种方式:使用tx标签配置的拦截器<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/beans"xmlns:xsi="/XMLSchema-instance"xmlns:context="/context"xmlns:aop="/aop"xmlns:tx="/tx"xsi:schemaLocation="/beans/beans/spring-beans-/context/context/spring-context-/aop /aop/spring-aop-/tx /tx/spring-tx-"><context:annotation-config/><context:component-scan base-package="com.bluesky"/><bean id="sessionFactory"class=""><property name="configLocation"value="classpath:"/><property name="configurationClass"value=""/></bean><!--定义事务管理器(声明式的事务)--><bean id="transactionManager"class=""><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(* "/><aop:advisor advice-ref="txAdvice"pointcut-ref="interceptorPointCuts"/></aop:config></beans>第五种方式:全注解<?xml version="1.0" encoding="UTF-8"?><beans xmlns="/beans"xmlns:xsi="/XMLSchema-instance"xmlns:context="/context"xmlns:aop="/aop"xmlns:tx="/tx"xsi:schemaLocation="/beans/beans/spring-beans-/context/context/spring-context-/aop /aop/spring-aop-/tx /tx/spring-tx-"><context:annotation-config/><context:component-scan base-package="com.bluesky"/><tx:annotation-driven transaction-manager="transactionManager"/><bean id="sessionFactory"class=""><property name="configLocation"value="classpath:"/><property name="configurationClass"value=""/></bean><!--定义事务管理器(声明式的事务)--><bean id="transactionManager"class=""><property name="sessionFactory"ref="sessionFactory"/></bean></beans>package;import;import;import;import;import;import;@Transactional@Component("userDao")public class UserDaoImpl extends HibernateDaoSupport implements UserDao {public List<User>listUsers() {return this.getSession().createQuery("from User").list();}}注意的几点:1、@Transactional只能被应用到public方法上,对于其他非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能。
propagation策略
Propagation策略是Spring框架中事务管理的一个关键属性,它决定了事务如何在不同的方法之间传播。
具体来说,Propagation策略定义了当一个事务方法被另一个事务方法调用时,应该如何使用事务。
以下是Spring中定义的几种Propagation策略:
1.PROPAGATION_REQUIRED:这是最常见的选择。
如果当前存在事务,那么就加入到这个事务中。
如果当前没有事务,就新建一个事务。
2.PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
3.PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
5.PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。
如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的
操作。
以上就是Spring中定义的所有Propagation策略。
这些策略可以帮助你更灵活地管理你的事务,以满足不同的业务需求。
实验十四 Spring事务处理
实验十四 Spring事务处理
一、实验目的
1.掌握基于注解管理事务的方式
2.熟悉基于XML配置方式管理事务
二、实验环境
1.Tomcat
2. MyEclipse
三、实验描述
Student的表结构(注:id为自动递增):
1.根据上述Student的表结构,使用注解管理事务的方式实现以下功能:
1)以新开一个事务的方式持久化两个Student实体到数据库表;
2)以只读事务方式读取id=1的实体;
3)必须要在一个事务中执行修改id=1的实体的姓名,否则抛出异常;
4)在默认的事务传播行为执行删除id=2的实体
5)在客户端调用执行各个方法,查看操作是否成功。
2.使用XML配置方式管理事务实现以上功能
四.实验步骤:
①创建一个java项目
②搭建Spring和Hibernate运行环境:把以下JAR文件构建到项目中
③编写持久化类及其映射文件
④创建一个Dao接口及其实现类
⑤创建一个业务接口及其实现类
⑥在src目录下新建一个Spring的配置文件
⑦创建测试类。
Spring声明式事务注解之@EnableTransactionManagement解析
Spring声明式事务注解之@EnableTransactionManagement解析Spring声明式事务注解之@EnableTransactionManagement1. 说明@EnableTransactionManagement声明在主配置类上,表⽰开启声明式事务,其原理是通过@Import导⼊TransactionManagementConfigurationSelector组件,然后⼜通过TransactionManagementConfigurationSelector导⼊组件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;2. 原理分析@EnableTransactionManagement代码实现如下:@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented// 通过@Import导⼊TransactionManagementConfigurationSelector组件@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement {boolean proxyTargetClass() default false;AdviceMode mode() default AdviceMode.PROXY;int order() default Ordered.LOWEST_PRECEDENCE;}@EnableTransactionManagement通过@Import导⼊TransactionManagementConfigurationSelector;TransactionManagementConfigurationSelector的实现如下:public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {/*** {@inheritDoc}* @return {@link ProxyTransactionManagementConfiguration} or* {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and* {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively*/@Overrideprotected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:// 根据@EnableTransactionManagement的固定值PROXY,这⾥会导⼊AutoProxyRegistrar组件和ProxyTransactionManagementConfiguration组件 return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};default:return null;}}}所以TransactionManagementConfigurationSelector⼜导⼊了组件AutoProxyRegistrar和ProxyTransactionManagementConfiguration;3. AutoProxyRegistrar分析3.1 AutoProxyRegistrar继承关系InfrastructureAdvisorAutoProxyCreator--AbstractAdvisorAutoProxyCreator--AbstractAdvisorAutoProxyCreator--ProxyProcessorSupport--SmartInstantiationAwareBeanPostProcessor // 跟AOP是原理是⼀样的--InstantiationAwareBeanPostProcessor--BeanPostProcessor--BeanFactoryAware3.2 AutoProxyRegistrar的所⽤AutoProxyRegistrar的作⽤跟AOP中的AnnotationAwareAspectJAutoProxyCreator是⼀样的,利⽤后置处理器机制在对象创建以后,包装对象,返回⼀个代理对象(增强器),代理对象执⾏⽅法利⽤拦截器链进⾏调⽤;InfrastructureAdvisorAutoProxyCreator继承SmartInstantiationAwareBeanPostProcessor,跟AOP的原理是⼀样的,也是通过@Transactional作为⽅法拦截的标记,把有事务管理的类作为⽬标类,⽣成代理对象,然后增强@Transactional标记的⽅法,在使⽤⽬标⽅法的时候,从IOC容器中获取的其实是被增强的代理类,且事务⽅法会被代理,跟AOP原理⼀样的;4. ProxyTransactionManagementConfiguration分析ProxyTransactionManagementConfiguration是⼀个配置类,想IOC容器中导⼊事务增强器(BeanFactoryTransactionAttributeSourceAdvisor),事务注解@Transactional的解析器(AnnotationTransactionAttributeSource)和事务⽅法拦截器(TransactionInterceptor);package org.springframework.transaction.annotation;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Role;import org.springframework.transaction.config.TransactionManagementConfigUtils;import org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor;import org.springframework.transaction.interceptor.TransactionAttributeSource;import org.springframework.transaction.interceptor.TransactionInterceptor;@Configurationpublic class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {/**事务增强器(Advisor),在事务类创建的时候,被AutoProxyRegistrar导⼊的组件InfrastructureAdvisorAutoProxyCreator拦截,InfrastructureAdvisorAutoProxyCreator拦截的逻就是增强事务类的事务⽅法,⽽BeanFactoryTransactionAttributeSourceAdvisor作为增强器,与需要增强的⽅法(这⾥是指被@Transactional标记的⽅法)进⾏匹配,匹配成功的增强器,最后转成拦截器(MethodInterceptor,就是下⾯的TransactionInterceptor),然后与⽬标⽅法⼀起在拦截器链中被执⾏,达到⽅法增强的效果;BeanFactoryTransactionAttributeSourceAdvisor的继承关系如下:BeanFactoryTransactionAttributeSourceAdvisor--AbstractBeanFactoryPointcutAdvisor--AbstractPointcutAdvisor--PointcutAdvisor--AdvisorAOP中AspectJPointcutAdvisor的继承关系如下,与AbstractPointcutAdvisor⼀样,都实现PointcutAdvisor--AspectJPointcutAdvisor--PointcutAdvisor--Advisor*/@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());advisor.setAdvice(transactionInterceptor());advisor.setOrder(this.enableTx.<Integer>getNumber("order"));return advisor;}/**@Transactional注解的解析类;负责解析事务⽅法上@Transactional中的各个参数配置,解析的时机是在创建事务类之后被增强的时候,匹配事务⽅法的时候⼀起被解析了AnnotationTransactionAttributeSource的继承关系如下:AnnotationTransactionAttributeSource--AbstractFallbackTransactionAttributeSource--TransactionAttributeSource通过⽅法org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>)解析出事务信息TransactionAttribute;AnnotationTransactionAttributeSource在⽅法findTransactionAttribute(Class<?>)中依赖于SpringTransactionAnnotationParser在解析事务类时,绑定事务⽅法与增强器的时候进⾏@Transactional注解解析;*/@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}/**被@Transactional标记的事务⽅法的拦截器,实际是⼀个MethodInterceptor保存了事务属性信息,事务管理器;在⽬标⽅法执⾏的时候;执⾏拦截器链;*/@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());if (this.txManager != null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}}在SpringTransactionAnnotationParser中parseTransactionAnnotation⽅法来解析@Transactional中的各个参数,其具体代码如下:protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");rbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");rbta.setIsolationLevel(isolation.value());rbta.setTimeout(attributes.getNumber("timeout").intValue());rbta.setReadOnly(attributes.getBoolean("readOnly"));rbta.setQualifier(attributes.getString("value"));ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();Class<?>[] rbf = attributes.getClassArray("rollbackFor");for (Class<?> rbRule : rbf) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}String[] rbfc = attributes.getStringArray("rollbackForClassName");for (String rbRule : rbfc) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");for (Class<?> rbRule : nrbf) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}String[] nrbfc = attributes.getStringArray("noRollbackForClassName");for (String rbRule : nrbfc) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}rbta.getRollbackRules().addAll(rollBackRules);return rbta;}spring 事务 @EnableTransactionManagement原理@EnableXXX原理:注解上有个XXXRegistrar,或通过XXXSelector引⼊XXXRegistrar,XXXRegistrar实现了ImportBeanDefinitionRegistrar的registerBeanDefinitions⽅法,给容器注册XXXCreator。
spring事务详解(基于注解和声明的两种实现方式)
spring事务详解(基于注解和声明的两种实现⽅式)Spring事务( Transaction )事务的概念事务是⼀些sql语句的集合,作为⼀个整体执⾏,⼀起成功或者⼀起失败。
使⽤事务的时机⼀个操作需要多天sql语句⼀起完成才能成功程序中事务在哪⾥说明加在业务类的⽅法上⾯(public⽅法上⾯),表⽰业务⽅法执⾏时,需要事务的⽀持。
不同的事务管理器不同的数据库访问技术,处理事务是不同的1. 使⽤jdbc访问数据库,事务处理public void updateAccount(){Connection con = .....;con.setAutoCommit(false);state.insert();state.update();mit();con.setAutoCommit(true);}2. MyBatis执⾏数据库,处理事务public void updateAccount(){SqlSession sqlSession = SqlSessionFactory.openSession(false);try{sqlSession.insert(...);sqlSession.update(...);mit();}catch(Exception e){sqlSession.rollback();}}spring统⼀管理事务,把不同的数据库访问技术的事务处理统⼀起来使⽤spring的事务管理器,管理不同数据库访问技术的事务处理。
开发⼈员只需要掌握spring的事务处理⼀个⽅案,就可以实现使⽤不同数据库访问技术的事务管理。
尽管事务⾯向的是spring,有spring管理事务,做事务提交和回滚。
spring事务管理器spring框架使⽤事务管理器对象,管理所有的事务。
事务管理器接⼝: PlatFormTransactionManager作⽤:定义了事务的操作,主要是commit() , rollback()事务管理器有很多的实现类:⼀种数据库访问计数有⼀个实现类。
Spring2.5声明式事务管理详解
大多数Spring用户选择声明式事务管理。
这是对应用代码影响最小的选择,因此也最符合非侵入式轻量级容器的理念。
Spring的声明式事务管理是通过Spring AOP实现的,因为事务方面的代码与Spring绑定并以一种样板式风格使用,不过尽管如此,你一般并不需要理解AOP概念就可以有效地使用Spirng的声明式事务管理。
从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。
它们的基本方法是相似的:都可以指定事务管理到单独的方法;如果需要可以在事务上下文调用setRollbackOnly()方法。
不同之处在于:∙不像EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。
只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作。
∙Spring的声明式事务管理可以被应用到任何类(以及那个类的实例)上,不仅仅是像EJB那样的特殊类。
∙Spring提供了声明式的回滚规则:EJB没有对应的特性,我们将在下面讨论。
回滚可以声明式的控制,不仅仅是编程式的。
∙Spring允许你通过AOP定制事务行为。
例如,如果需要,你可以在事务回滚中插入定制的行为。
你也可以增加任意的通知,就象事务通知一样。
使用EJB CMT,除了使用setRollbackOnly(),你没有办法能够影响容器的事务管理。
∙Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。
如果你需要这些特性,我们推荐你使用EJB。
然而,不要轻易使用这些特性。
因为通常我们并不希望事务跨越远程调用。
TransactionProxyFactoryBean在哪儿?Spring2.0及以后的版本中声明式事务的配置与之前的版本有相当大的不同。
主要差异在于不再需要配置TransactionProxyFactoryBean了。
Spring2.0之前的旧版本风格的配置仍然是有效的;你可以简单地认为新的<tx:tags/>替你定义了T ransactionProxyFactoryBean。
spring,mybatis事务管理配置与@Transactional注解使用[转]
spring,mybatis事务管理配置与@Transactional注解使用[转]spring,mybatis事务管理配置与@Transactional注解使用概述事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。
Spring Framework对事务管理提供了一致的抽象,其特点如下:为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用提供比其他事务API如JTA更简单的编程式事务管理API与spring数据访问抽象的完美集成事务管理方式spring支持编程式事务管理和声明式事务管理两种方式。
编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。
对于编程式事务管理,spring推荐使用TransactionTemplate。
声明式事务管理建立在AOP之上的。
其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
显然声明式事务管理要优于编程式事务管理,这正是spring 倡导的非侵入式的开发方式。
声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。
和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
java中的事务回滚_Spring中的事务回滚机制
java中的事务回滚_Spring中的事务回滚机制在Java中,事务回滚是指将数据库操作还原到事务开始之前的状态,以保证数据的一致性和完整性。
Spring框架提供了一套完整的事务管理机制,可以在应用开发中灵活地使用。
Spring中的事务回滚机制主要涉及以下几个关键概念:1. 事务管理器(Transaction Manager):Spring框架中的事务管理器是用于管理事务的核心组件。
它负责管理事务的开始、提交和回滚等操作。
Spring支持多个事务管理器,包括JDBC事务、JTA事务以及支持特定数据源的事务管理器。
2. 事务定义(Transaction Definition):事务定义是事务配置的一部分,它定义了事务的隔离级别、传播行为和超时时间等信息。
事务定义可以通过XML配置文件或注解的形式进行描述。
3. 事务传播行为(Transaction Propagation):事务传播行为定义了在方法调用链中如何传播事务的规则。
Spring提供了多种事务传播行为,包括REQUIRED、SUPPORTS、REQUIRES_NEW等。
这些传播行为可以根据具体的业务需求进行选择,以实现灵活的事务管理。
4. 事务切面(Transaction Aspect):Spring框架通过AOP(Aspect-Oriented Programming)实现了事务管理的切面机制。
事务切面在方法调用前后,以及在异常抛出时执行相应的操作,包括事务开启、提交和回滚等。
5. 事务注解(Transaction Annotation):6. 异常回滚(Exception Rollback):在Spring事务管理中,可以通过配置特定的异常类型来触发事务回滚操作。
当方法中抛出指定的异常时,事务会被回滚到事务的起始点。
Spring中的事务管理主要有两种方式:编程式事务管理和声明式事务管理。
编程式事务管理是通过编写代码来手动控制事务的开始、提交和回滚等操作。
【笔试题】Spring笔试题
【笔试题】Spring笔试题spring笔试题1.Spring⽀持的事务管理类型Spring⽀持两种类型的事务管理:编程式事务管理:这意味你通过编程的⽅式管理事务,给你带来极⼤的灵活性,但是难维护。
声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需⽤注解和XML配置来管理事务。
你更倾向⽤那种事务管理类型?⼤多数Spring框架的⽤户选择声明式事务管理,因为它对应⽤代码的影响最⼩,因此更符合⼀个⽆侵⼊的轻量级容器的思想。
声明式事务管理要优于编程式事务管理,虽然⽐编程式事务管理(这种⽅式允许你通过代码控制事务)少了⼀点灵活性。
2.什么是控制反转(IOC)?什么是依赖注⼊?控制反转是应⽤于软件⼯程领域中的,在运⾏时被装配器对象来绑定耦合对象的⼀种编程技巧,对象之间耦合关系在编译时通常是未知的。
在传统的编程⽅式中,业务逻辑的流程是由应⽤程序中的早已被设定好关联关系的对象来决定的。
在使⽤控制反转的情况下,业务逻辑的流程是由对象关系图来决定的,该对象关系图由装配器负责实例化,这种实现⽅式还可以将对象之间的关联关系的定义抽象化。
⽽绑定的过程是通过“依赖注⼊”实现的。
控制反转是⼀种以给予应⽤程序中⽬标组件更多控制为⽬的设计范式,并在我们的实际⼯作中起到了有效的作⽤。
依赖注⼊是在编译阶段尚未知所需的功能是来⾃哪个的类的情况下,将其他对象所依赖的功能对象实例化的模式。
这就需要⼀种机制⽤来激活相应的组件以提供特定的功能,所以依赖注⼊是控制反转的基础。
否则如果在组件不受框架控制的情况下,框架⼜怎么知道要创建哪个组件?在Java中依赖注⼊有以下三种实现⽅式:1、构造器注⼊2、Setter⽅法注⼊3、接⼝注⼊控制反转依赖注⼊反转是相对于正向⽽⾔的,那么什么算是正向的呢?考虑⼀下常规情况下的应⽤程序,如果要在A⾥⾯使⽤C,你会怎么做呢?当然是直接去创建C的对象,也就是说,是在A类中主动去获取所需要的外部资源C,这种情况被称为正向的。
基于Spring的事务管理研究
事 务 处 理 , 可 以运 用 其 例 外 阶层 的优 点 。 并 S r g在 事 务 管理 上 可 以提 供 一 致 性 的 模 型 ,你 可 以使 用 声 pn i 明式 的事务管理 , 如此 你 的 组 件 就 不 用 介 入 事 务 处 理 , 由 A P 就 O 介 入 组 件 进 行 事 务 管 理 , 务 管 理 只 需 要 在 定 义 档 中作 一 些 选 项 事 修 改 . 于 组 件并 不介 入 实 质 的 事 务 处 理 , 可 以设 计 得 更 通 用 , 由 它
而 改 变 事 务 处 理 策 略 , 味 着 你 只 要 改 变 定 义 档 的 设 定 , 不 用 意 而
任务失败 , 则第一个任务 回滚到创建新表前的点。
如此 例 所 示 , 将 事 务 限 制 到 一 个 数 据 资 源 , 数 据 库 或 消 可 如 息 队列 。这 些数 据 资 源 通 常提 供 本 地 事 务 功 能 。这 些事 务 由数 据 资源 控 制 . 理起 来 轻 松 高 效 。 务还 可 以跨 越 多个 数 据 资 源 。 管 事 分 布 式 事 务 使 你 得 以 将 出现 在 不 同 系 统 上 的若 干 不 同操 作 合 并 为 单 个 的成 功 或 失 败操 作 。
维普资讯
・
开 发 研 究 与 设 计 技 术 ・ ・ ・ ・・ ・
本 目 任 辑 谢 媛 栏 责 编 : 媛
基于 S r g的事务 管理研 究 pi n
金导 航
( 武汉 警 官 职 业 学 院 , 北 武 汉 4 04 ) 湖 30 0
摘 要 : 文描 述 了事 务 管理 机 制 的 基 本 原理 及 S r g的 简介 , 点 说 明 了 S r g的 编 程 式 事 务 管理 和 声 明 式 事 务 管理 。 本 pn i 重 pn i
springboot中事务管理@Transactional的注意事项与使用场景
springboot中事务管理@Transactional的注意事项与使⽤
场景
前⾔:在service层的⽅法上使⽤@Transactional 即可实现处理数据库发⽣错误时触发事务回滚机制。
注意:
Spring 基于注解的声明式事物 @Transactional 默认情况下只会对运⾏期异常(ng.RuntimeException及其⼦类)和Error 进⾏回滚。
数据库引擎要⽀持事物,使⽤InnoDB。
@Transactional 只能被应⽤到public⽅法上, 对于其它⾮public的⽅法,如果标记了@Transactional也不会报错,但⽅法没有事务功能.
具体使⽤场景:
在service⽅法中不使⽤try-catch显⽰处理异常,直接throw new runtimeexcetpion()可实现事务回滚
在service⽅法中使⽤try-catch,但是需要在catch中加上throw new runtimeexcetpion()可实现事务回滚
注意当⽅法加上synchronized时,由于锁的作⽤范围⽐事务的作⽤范围⼩,因此应该修改锁的作⽤范围,保证锁的范围⽐事务的范围⼤即可。
总结
以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,谢谢⼤家对的⽀持。
如果你想了解更多相关内容请查看下⾯相关链接。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
9.5. 声明式事务管理大多数Spring用户选择声明式事务管理。
这是对应用代码影响最小的选择,因此也最符合非侵入式轻量级容器的理念。
Spring的声明式事务管理是通过Spring AOP实现的,因为事务方面的代码与Spring绑定并以一种样板式风格使用,不过尽管如此,你一般并不需要理解AOP概念就可以有效地使用Spirng的声明式事务管理。
从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。
它们的基本方法是相似的:都可以指定事务管理到单独的方法;如果需要可以在事务上下文调用setRollbackOnly()方法。
不同之处在于:∙不像EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。
只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作。
∙Spring的声明式事务管理可以被应用到任何类(以及那个类的实例)上,不仅仅是像EJB那样的特殊类。
∙Spring提供了声明式的回滚规则:EJB没有对应的特性,我们将在下面讨论。
回滚可以声明式的控制,不仅仅是编程式的。
∙Spring允许你通过AOP定制事务行为。
例如,如果需要,你可以在事务回滚中插入定制的行为。
你也可以增加任意的通知,就象事务通知一样。
使用EJB CMT,除了使用setRollbackOnly(),你没有办法能够影响容器的事务管理。
∙Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。
如果你需要这些特性,我们推荐你使用EJB。
然而,不要轻易使用这些特性。
通常我们并不希望事务跨越远程调用。
TransactionProxyFactoryBean在哪儿?Spring2.0及以后的版本中声明式事务的配置与之前的版本有相当大的不同。
主要差异在于不再需要配置TransactionProxyFactoryBean了。
Spring2.0之前的旧版本风格的配置仍然是有效的;你可以简单地认为新的<tx:tags/>替你定义了TransactionProxyFactoryBean。
回滚规则的概念比较重要:它使我们能够指定什么样的异常(和throwable)将导致自动回滚。
我们在配置文件中声明式地指定,无须在Java代码中。
同时,我们仍旧可以通过调用TransactionStatus的setRollbackOnly()方法编程式地回滚当前事务。
通常,我们定义一条规则,声明MyApplicationException必须总是导致事务回滚。
这种方式带来了显著的好处,它使你的业务对象不必依赖于事务设施。
典型的例子是你不必在代码中导入Spring API,事务等。
对EJB来说,默认的行为是EJB容器在遇到系统异常(通常指运行时异常)时自动回滚当前事务。
EJB CMT 遇到应用异常(例如,除了java.rmi.RemoteException外别的checked exception)时并不会自动回滚。
默认式Spring处理声明式事务管理的规则遵守EJB习惯(只在遇到unchecked exceptions时自动回滚),但通常定制这条规则会更有用。
9.5.1. 理解Spring的声明式事务管理实现本节的目的是消除与使用声明式事务管理有关的神秘性。
简单点儿总是好的,这份参考文档只是告诉你给你的类加上@Transactional注解,在配置文件中添加('<tx:annotation-driven/>')行,然后期望你理解整个过程是怎么工作的。
此节讲述Spring的声明式事务管理内部的工作机制,以帮助你在面对事务相关的问题时不至于误入迷途,回朔到上游平静的水域。
提示阅读Spring源码是理解清楚Spring事务支持的一个好方法。
Spring的Javadoc提供的信息丰富而完整。
我们建议你在开发自己的Spring应用时把日志级别设为'DEBUG'级,这样你能更清楚地看到幕后发生的事。
在理解Spring的声明式事务管理方面最重要的概念是:Spring的事务管理是通过AOP代理实现的。
其中的事务通知由元数据(目前基于XML或注解)驱动。
代理对象与事务元数据结合产生了一个AOP代理,要把AnnotationTransactionAspect织入你的应用,你或者基于AspectJ构建你的应用(参考AspectJ Development Guide),或者采取“载入时织入”(load-time weaving),参考第 6.8.4 节“在Spring应用中使用AspectJ Load-time weaving(LTW)”获得关于使用AspectJ进行“载入时织入”的讨论环境:JDK 1.4.x , Hibernate 3.1, Spring 2.0.6, 开发模式: Service + DAO 1. 代理工厂Bean事务管理( *ProxyFactoryBean) + Service + DAO配置我刚开始看Spring时用的书是林信良的《Spring技术手册》,书中对声明式事务主要采用 TransactionProxyFactoryBean,业务Bean如 Service或BO 类继承它来进行事务控制。
代理工厂Bean( *ProxyFactoryBean)这一类Spring 提供的工厂类,可将一个 bean 进行委托代理,从而达到控制方法行为的目的。
此类事务配置一般如下(因为我们未采用这种方式,就以书上的JDBC datasource举例说明。
不同公司采用的格式可能有所不同):Xml代码1.<!-- 前面的 dataSource等配置略 ........ -->2.3.<!-- 事务管理器 -->4.<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">5.<property name="dataSource">6.<ref local="dataSource"/>7.</property>8.</bean>9.10.<!-- 事务模板 -->11.<bean id="baseTransactionProxy"12.class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"13.abstract="true">14.<property name="transactionManager"ref="transactionManager"/>15.<property name="transactionAttributes">16.<props>17.<prop key="*">PROPAGATION_REQUIRED</prop> <!-- 本文仅简单用一种方式说明。
所有方法起事务,可以修改以精细和区别性控制事务 -->18.</props>19.</property>20.</bean>21.22.23.<!-- 业务对象 -->24.<bean id="authService"parent="baseTransactionProxy">25.<property name="target">26.<bean class="com.xxxx.cms.service.AuthorityService">27.<property name="authDao"ref="authDao"/>28.</bean>29.</property>30.</bean>31.<bean id="departmentService"parent="baseTransactionProxy">32.<property name="target">33.<bean class="com.xxxx.cms.service.pojo.DepartmentService">34.<property name="departmentDao"ref="departmentDao"/>35.</bean>36.</property>37.</bean>38.<!-- 数据访问对象 -->39.<bean id="authDao"class="com.xxxx.cms.dao.jdbc.AuthorityDao">40.<property name="dataSource"ref="dataSource"/>41.</bean>42.<bean id="departmentDao"class="com.xxxx.cms.dao.jdbc.DepartmentDao">43.<property name="dataSource"ref="dataSource"/>44.</bean>这种代理工厂Bean的事务管理一般都要求将 Service 的 bean 配置为class="org.springframework.transaction.interceptor.TransactionProxyFa ctoryBean" ,上面的例子使用了 parent="baseTransactionProxy" 继承机制简化了原书中的配置。