8 -- 深入使用Spring -- 6...2 Spring支持的事务策略
8.6.2 使用XML Schema配置事务策略
Spring 同时支持编程式事务策略和声明式事务策略,通常都推荐采用声明式事务策略。
⊙ 声明式事务能大大降低开发者的代码书写量,而且声明式事务几乎不影响应用的代码。因此,无论底层事务策略如何变化,应用程序都无须任何改变。
⊙ 应用程序代码无须任何事务处理代码,可以更专注于业务逻辑的实现。
⊙ Spring则可对任何POJO的方法提供事务管理,而且Spring的声明式事务管理无须容器的支持,可在任何环境下使用。
⊙ EJB的CMT无法提供声明式回滚规则:而通过配置文件,Spring可指定事务在遇到特定异常时自动回滚。
⊙ 由于Spring采用AOP的方式管理事务,因此,可以在事务回滚动作中插入用户自己的动作,而不仅仅是执行系统默认的回滚。
Spring 2.x 的XML Schema方式提供了简洁的事务配置策略,Spring 2.x提供了 tx:命名空间 来配置事务管理,tx:命名空间下提供了<tx:advice.../>元素来配置事务增强处理,一旦使用该元素配置了事务增强处理,就可直接使用<aop:advisor.../>元素启用自动代理了。
配置<tx:advice.../>元素时除了需要transaction-manager属性指定事务管理器之外,还需要配置一个<attributes.../>子元素,该子元素里又可包含多个<method.../>子元素。
配置<tx:advice.../>元素的重点就是配置<method.../>子元素,实际上每个<method.../>子元素都为一批方法指定了所需的事务定义,包括事务传播属性、事务隔离属性、事务超时属性、只读事务、对指定异常回滚、对指定异常不回滚等。
配置<method.../>子元素可以指定如下属性:
⊙ name : 必选属性,与该事务语义关联的方法名。该属性支持使用通配符,例如:‘add*’、‘delete*’、‘get*byId’、‘update*’等。
⊙ propagation : 指定事务传播行为,该属性值可为Propagation枚举类的任一枚举值。该属性的默认值为Propagation.REQUIRED。
⊙ isolation : 指定事务隔离级别,该属性值可为Isolation枚举类的任一枚举值。默认值为Isolation.DEFAULT。
⊙ timeout : 指定事务超时的时间(以秒为单位),指定-1意味着不超时,该属性默认值是-1.
⊙ read-only : 指定事务是否只读。该属性的默认值是false。
⊙ rollback-for : 指定触发事务回滚的异常类(应使用全限定类名),该属性可指定多个异常类,多个异常类之间以英文逗号隔开。
⊙ no-rollback-for : 指定不触发事务回滚的异常类(应使用全限定类名),该属性可指定多个异常类,多个异常类之间以英文逗号隔开。
<method.../>子元素的propagation属性用于指定事务传播行为,Spring支持的事务传播行为如下:
⊙ PROPAGATION_MANDATORY(强制的) : 要求调用方法的线程必须处于事务环境中,否则抛出异常。
⊙ PROPAGATION_NEVER(决不) : 不允许调用该方法的线程处于事务中,如果调用该方法的线程处于事务环境中,则抛出异常。
⊙ PROPAGATION_SUPPORTS(支持) : 如果当前执行线程处于事务环境中,则使用当前事务,否则不使用事务。
⊙ PROPAGATION_NOT_SUPPORED (被支持的): 如果调用该方法的线程处于事务环境中,则先暂停当前事务,然后执行该方法。
⊙ PROPAGATION_NESTED(嵌套的) : 即使执行该方法的线程已处于事务环境中,也依然启动新的事务,方法在嵌套的事务里执行;即使执行该方法的线程并未处于事务环境中,也启动新的事务,然后执行该方法,此时与PROPAGATION_REQUIRED相同。
⊙ PROPAGATION_REQUIRED(必需的) : 要求在事务环境中执行该方法,如果当前执行线程已处于事务环境中,则直接调用;如果当前执行线程不处于事务环境中,则启动新的事务后执行该方法。
⊙ PROPAGATION_REQUIES_NEW (需求): 该方法要求在新的事务环境中执行,如果当前执行线程已处于事务环境中,则先暂停当前事务,启动新事物后执行该方法;如果当前调用线程不处于事务环境中,则启动新的事务后执行方法。
Class : NewsDaoImpl
package edu.pri.lime._8_6_2.dao;import javax.sql.DataSource;import org.springframework.jdbc.core.JdbcTemplate;public class NewsDaoImpl implements NewsDao {private DataSource ds;public void setDs(DataSource ds) {this.ds = ds;}@Overridepublic void insert(String title, String content) {JdbcTemplate jt = new JdbcTemplate(ds);jt.update("insert into news_inf values(null,?,?)", title, content);// 两次插入的数据违反唯一键约束jt.update("insert into news_inf values(null,?,?)", title, content);// 如果没有事务控制,则第一条记录可以被插入// 如果增加事务控制,将发现第一条记录也插不进去 }}
XML :
<?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"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-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_2.dao"/><!-- 定义数据源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.spring.framework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 配置一个业务逻辑Bean --><bean id="newsDao" class="edu.pri.lime._8_6_2.dao.NewsDaoImpl"><property name="ds" ref="dataSource"/></bean><!-- 配置事务增强处理Bean,指定事务管理器 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 用于配置详细的事务定义 --><tx:attributes><!-- 所有以get开头的方法是只读的 --><tx:method name="get*" read-only="true"/><!-- 其他方法使用默认的事务设置,指定超时时长为5秒 --><tx:method name="*" isolation="DEFAULT" propagation="REQUIRED" timeout="5"/></tx:attributes></tx:advice><!-- AOP配置的元素 --><aop:config><!-- 配置一个切入点,匹配edu.pri.lime._8_6_2.dao包下所有以Impl结尾的类里所有方法的执行 --><aop:pointcut expression="execution(* edu.pri.lime._8_6_2.dao.*Impl.*(..))" id="myPointcut"/><!-- 指定在myPointcut切入点应用txAdvice事务增强处理 --><aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/></aop:config> </beans>
Class : SpringTest
package edu.pri.lime._8_6_2;import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import edu.pri.lime._8_6_2.dao.NewsDao; import edu.pri.lime._8_6_2.dao.NewsDaoImpl;public class SpringTest {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_6_2_tx.xml");// 获取事务代理BeanNewsDao dao = ctx.getBean("newsDao", NewsDaoImpl.class);// 执行插入操作dao.insert("lime", "Oracle");} }
当使用<tx:advisor.../>为目标Bean生成事务代理之后,SpringAOP将会把负责事务操作的增强处理织入目标Bean的业务方法中。
Spring 不仅支持对接口的代理,而且也可对具体类生成代理,只要设置proxytargetClass属性为true既可以了。如果目标Bean没有实现热河接口,proxyTargetClass属性默认被设为true,此时Spring会对具体类生成代理。当然,通常建议面向接口编程,而不要面向具体的实现类编程。
当采用<aop:advisor.../>元素将Advice和切入点绑定时,实际上是由Spring提供的Bean后处理器完成的。Spring提供了BeanNameAutoProxyCreator、DefaultAdvisorAutoProxyCreator两个Bean后处理器,它们都可以对容器中的Bean执行后处理(为他们织入切面中包含的增强处理)。当配置<aop:advisor.../>元素时传入一个txAdvice事务增强处理,所以Bean后处理器将为所有Bean实例里匹配切入点的方法织入事务操作的增强处理。
在这种声明式事务策略下,Spring也允许为不同的业务逻辑方法指定不同的事务策略:
<?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"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-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_2.dao"/><!-- 定义数据源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.spring.framework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 配置一个业务逻辑Bean --><bean id="newsDao" class="edu.pri.lime._8_6_2.dao.NewsDaoImpl"><property name="ds" ref="dataSource"/></bean><!-- 配置两个事务增强处理 --><tx:advice id="txAdvice"><tx:attributes><tx:method name="get*" read-only="true"/><tx:method name="*"/></tx:attributes></tx:advice><tx:advice id="noTxAdvice"><tx:attributes><tx:method name="*" propagation="NEVER"/></tx:attributes></tx:advice><aop:config><!-- 配置一个切入点,匹配userService Bean 中所有方法的执行 --><aop:pointcut expression="bean(userService)" id="txOperation"/><!-- 配置一个切入点,匹配包下所有以Impl结尾的类中所有方法的执行 --><aop:pointcut expression="execution(* edu.pri.lime._8_6_2.dao.*Impl.*(..))" id="noTxOperation"/><!-- 将txOperation切入点和defaultTxAdvice切面绑定在一起 --><aop:advisor advice-ref="defaultTxAdvice" pointcut-ref="txOperation"/><!-- 将noTxOperation切入点和noTxAdvice切面绑定在一起 --><aop:advisor advice-ref="noTxAdvice" pointcut-ref="noTxOperation"/></aop:config><!-- 配置第一个业务逻辑Bean,该Bean的名字为userService,匹配txOperation切入点将被织入defaultTxAdvice切面里的增强处理 --><bean id="userService" class=""></bean><!-- 配置第二个业务逻辑Bean,实现类位于包下,将被织入noTxAdvice切面里的增强处理 --><bean id="anotherFooService" class=""/> </beans>
如果想让事务在遇到特定的cheched异常时自动回滚,则可借助于rollback-for属性。
在默认情况下,只有当方法引发运行时异常和unchecked异常时,Spring事务机制才会自动回滚事务。也就是说,只有当抛出一个RuntimeException或其子类实例,或Error对象时,Spring才会自动回滚事务。如果事务方法抛出checked异常,则事务不会自动回滚。
通过使用rollback-for属性可强制Spring遇到特定checked异常时自动回滚事务:
<?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"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="get*" read-only="true"rollback-for="exception.NoItemException" /><tx:method name="*" /></tx:attributes></tx:advice></beans>
如果想让Spring遇到特定runtime异常时强制不会滚事务,则可通过no-rollback-for属性来指定:
<?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"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="get*" read-only="true"no-rollback-for="exception.AuctionException" /><tx:method name="*" /></tx:attributes></tx:advice></beans>
啦啦啦
啦啦啦
啦啦啦
啦啦啦
啦啦啦
啦啦啦
啦啦啦
啦啦啦
啦啦啦
转载于:https://www.cnblogs.com/ClassNotFoundException/p/6596819.html
8 -- 深入使用Spring -- 6...2 Spring支持的事务策略相关推荐
- Java缓存学习之五:spring 对缓存的支持
(注意标题,Spring对缓存的支持 这里不单单指Ehcache ) 从3.1开始,Spring引入了对Cache的支持.其使用方法和原理都类似于Spring对事务管理的支持.Spring Cache ...
- Spring对AOP的支持
Spring对AOP的支持<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...
- 在controller中调用指定参数给指定表单_第005课:Spring Boot 中MVC支持
Spring Boot 的 MVC 支持主要介绍实际项目中最常用的几个注解,包括 @RestController. @RequestMapping.@PathVariable.@RequestPara ...
- Spring对JNDI的支持方法
Spring对JNDI的支持 Spring中对于JNDI的访问,提供了便捷的方法,在Spring的org.springframework.jndi包中包含了所有的类.其中提供了一下核心类: 1)Jnd ...
- Spring对java模块化支持_Spring项目对JDBC的支持和基本使用
欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系.本系列教程希望您能站在上帝 ...
- Spring Cloud Gateway 原生支持接口限流该怎么玩
关于pig: 基于Spring Cloud.oAuth2.0开发基于Vue前后分离的开发平台,支持账号.短信.SSO等多种登录,提供配套视频开发教程. 关于 Spring Cloud Gateway ...
- 由openSession、getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持
由openSession.getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持 Spring和Hibernate的集成的一个要点就是对事务的支持,op ...
- 如何理解Spring对缓存的支持
1.Spring缓存机制的理解 在Spring缓存机制中,包括了两个方面的缓存操作:1.缓存某个方法返回的结果:2.在某个方法执行前或后清空缓存. 下面写两个类来模拟Spring的缓存机制: pack ...
- CORS跨域资源共享(二):详解Spring MVC对CORS支持的相关类和API【享学Spring MVC】
每篇一句 重构一时爽,一直重构一直爽.但出了问题火葬场 前言 上篇文章通过我模拟的跨域请求实例和结果分析,相信小伙伴们都已经80%的掌握了CORS到底是怎么一回事以及如何使用它.由于Java语言中的w ...
最新文章
- post传值php取不到数据,post请求中的参数形式和form-data提交数据时取不到的问题...
- 人人都来写算法 之 快速排序
- 每周分享第7期(2019.5.18)
- SQL语句之left join、right join、inner join的区别
- sequelize连接mysql_node.js通过Sequelize 连接MySQL
- 隐藏画质代码_优秀的模糊测试代码是如何炼成的?
- 除了 Tensorflow、PyTorch ,还有哪些深度学习框架值得期待?
- (15)FPGA面试题存储器资源区别
- Spring Boot 核心原理与源码解析 - 目录
- python操控chrome抓网页
- r语言结构方程模型可视化_R语言时间序列分析(二):ts对象及其可视化
- hrbust/哈理工oj 1809 再就业【状压dp】
- 从阿尔法元的诞生看终极算法的可能性
- Java——单例模式:饿汉、懒汉模式
- java 农历公历转换_Java怎样编程实现农历和阳历转换?
- 新思课堂C语言答案,新思课堂APP最新版下载_新思课堂APP官方版1.6.8下载_QQ下载站...
- Carte+kettle+mysql性能问题定位分析记录
- mysql 8.0 用户修改为简单密码
- Java的泛型---(英雄联盟集合嵌套案例)
- 字典树学习 根据前缀词根建立字典树
热门文章
- 经验的总结,需要记录。
- UNetbootin | 轻松制作Linux/BSD安装引导U盘
- magento 2 引用 css,Magento2在Phtml文件中调用显示静态块
- perl oracle ppm,Perl图形化包管理工具PPM学习使用笔记
- springboot整合websocket进行消息推送
- python透明图片合并_如何使用PIL将透明png图像与另一个图像合并
- C语言查看tuxedo队列长度,tuxedo的常用启、停、参数讲解、日志查看
- 开源GIS(九)——openlayers中简单要素的添加与geojson数据修改添加
- VirtualBox扩容失败-Progress state: VBOX_E_NOT_SUPPORTED
- oracle服务器文件路径,ORACLE 数据库如何通过修改数据文件路径进行数据迁移