Spring事务管理——使用XML配置声明式事务
来源:互联网 发布:道路采集赚钱软件 编辑:程序博客网 时间:2024/06/05 05:27
林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
一、事务介绍
事务简介:
事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性
事务就是一系列的动作,它们被当作一个单独的工作单元。这些动作要么全部完成,要么全部不起作用。
事务的四个关键属性(ACID)
① 原子性(atomicity):事务室一个原子操作,有一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用
② 一致性(consistency):一旦所有事务动作完成,事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中
③ 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏
④ 持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中
数据隔离级别
隔离级别脏读不可重复读幻象读第一类丢失更新第二类丢失更新READ UNCOMMITED允许允许允许不允许允许READ COMMITED不允许允许允许不允许允许REPEATABLE READ不允许不允许允许不允许不允许SERIALIZABLE 不允许不允许不允许不允许不允许SqlServer2008R2的默认隔离级别是“READ COMMITED”,MySQL的默认隔离级别是“REPEATABLE READ”。
spring中的事务管理
作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层。而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制。
Spring既支持编程式事务管理,也支持声明式的事务管理
编程式事务管理:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码
声明式事务管理:大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring通过Spring AOP框架支持声明式事务管理。
Spring事务的传播属性:
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
事务的传播行为可以由传播属性指定。Spring定义了7种传播行为:
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务,加入到这个事务中。这是最常见的选择。PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。并发事务所导致的问题
在同一个应用程序或者不同应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题。
并发事务所导致的问题可以分为以下三类:
① 脏读:脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。
② 不可重复读:不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间更新了数据
③ 幻读:幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录
二、实例开发
Spring声明式事务让我们从复杂的事务处理中得到解脱,使得我们再也不必去处理获得连接、关闭连接、事务提交和回滚等这些操作,再也无需我们在与事务相关的方法中处理大量的try…catch…finally代码。
我们在使用Spring声明式事务时,有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为、事务的隔离级别、事务的超时值、事务只读标志组成。我们在进行事务划分时,需要进行事务定义,也就是配置事务的属性。 Spring在TransactionDefinition接口中定义这些属性,以供PlatfromTransactionManager使用,PlatfromTransactionManager是spring事务管理的核心接口。
下面用一个例子来说明Spring事务管理的好处
新建立一个Java工程,导入相关的包,事个工程最终目录如下:
本文工程免费下载
这里应用到了mysql,需要建立数据库test及其下的数据表book_table
1、数据表对应的model类:
2、接着是DAO层:
实现类:
3、事务配置
4、测试使用:输出结果:
这里只输出了一条
数据库中的结果:
5、上面是正常时的情况,现在我们想让它出现异常,并自动回滚。简单。
LibraryDaoImpl类中插入的时候多插一个相同的数据
然后先把数据库内容清空:其它地方都不变:
执行程序后:
检查数据库:
发现一条数据都没有插入进去,所以说全部都回滚了。
如果这时我们不用Spring的事务管理,插入还是插入两条相同的,结果又会怎么样?
把Test类中的
改成
其它还是不变执行后
发现在抛出异常后,还是插入了一条数据,说明没有回滚事务。
三、基于tx/aop的配置
之前学了AOP,可以在想要的类或方法前面或后面织入增强,同理也可以用到这里来
上面的beans.xml文件可以改写成如下:
AOP会自动将事务织入到相应的类的方法之上。重点代码如下
上面的这一段是重点。接下来要来测试一上,把之前的LibraryDaoImpl类中的方法改成如下:
这里就是想插入20条数据,但是第8条插入时抛出异常,所以说最终应该会回滚,也就是说,一条数据也没有。
测试类:
结果:然后看看数据库中有没有插入
那如果注释掉这一段,结果又会如何呢?把AOP增强给注释,其它都不变。理论来讲应该会提交了8条数据
其它都不变,执行结果:
结果表明,如果 不进行事务管理,如果 出现错误,还是提交了数据操作。这不符合要求!
四、一些说明
需要注意的地方:
(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标签就是把上面我们所配置的事务管理两部分属性整合起来作为整个事务管理。
<tx:method/>
有关的设置
name
是 与事务属性关联的方法名。通配符(*)可以用来指定一批关联到相同的事务属性的方法。如:'get*'
、'handle*'
、'on*Event'
等等。
propagation
不REQUIRED事务传播行为(配置文章开头)isolation
不DEFAULT事务隔离级别(配置看文章开头)propagation="REQUIRED"代表支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。timeout
不-1事务超时的时间(以秒为单位)read-only
不false事务是否只读?rollback-for
不 将被触发进行回滚的 Exception(s)
;以逗号分开。 如:'com.foo.MyBusinessException,ServletException'
no-rollback-for
不 不 被触发进行回滚的Exception(s)
;以逗号分开。 如:'com.foo.MyBusinessException,ServletException'
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
">
<!-- 数据源的配置 使用c3p0实现 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="initialPoolSize">
<value>${cpool.initialPoolSize}</value>
</property>
<property name="acquireIncrement">
<value>${cpool.acquireIncrement}</value>
</property>
<property name="minPoolSize">
<value>${cpool.minPoolSize}</value>
</property>
<property name="maxPoolSize">
<value>${cpool.maxPoolSize}</value>
</property>
<property name="maxIdleTime">
<value>${cpool.maxIdleTime}</value>
</property>
<property name="autoCommitOnClose">
<value>${cpool.autoCommitOnClose}</value>
</property>
<property name="idleConnectionTestPeriod" value="${cpool.idleConnectionTestPeriod}" />
<property name="testConnectionOnCheckout" value="${cpool.testConnectionOnCheckout}" />
<!-- <property name="automaticTestTable" value="${cpool.automaticTestTable}" /> -->
<property name="preferredTestQuery"><value>SELECT 1</value></property>
</bean>
<!-- 声明式事务管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="get*"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="select*" read-only="true"/>
<tx:method name="update*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="point" expression="execution(* com.gongsi.starauction.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="point"/>
</aop:config>
<!-- *Service 应为*ServiceImpl -->
<!--<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="del*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="release*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<value>*Service</value>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean> -->
</beans>
- Spring事务管理——使用XML配置声明式事务
- Spring事务管理——使用XML配置声明式事务
- Spring事务管理——使用XML配置声明式事务
- Spring事务管理——使用XML配置声明式事务
- Spring声明式事务管理、事务的传播行为xml配置
- Spring事务管理(XML配置声明式)
- spring使用xml进行声明式事务管理
- 使用Spring的XML声明式事务管理
- spring事务管理-声明式事务
- Spring整合hibernate的事务属性介绍以及声明式事务管理 (使用Annotation和xml)
- Spring整合hibernate的事务属性介绍以及声明式事务管理 (使用Annotation和xml)
- Spring JDBC-使用XML配置声明式事务
- spring事务配置,声明式事务管理和基于@Transactional注解的使用
- spring丶基于@Transactional注解的事务配置,声明式事务管理的使用
- spring事务配置,声明式事务管理和基于@Transactional注解的使用
- Spring事务配置,声明式事务管理和基于@Transactional注解的使用
- Spring声明式事务XML配置
- Spring声明式事务管理之xml事务管理
- 使用docker run的选项以覆盖Dockerfile中的设置详解
- ubuntu16.04下chrome安装flash插件
- Android 常用控件(四)
- 模拟上帝之手的对抗博弈——GAN背后的数学原理
- SRWebSocket源码浅析(上)
- Spring事务管理——使用XML配置声明式事务
- bootstrap upload 文件上传的实现过程
- OpenGL笔试题
- jhipster命令
- 【Python那些事儿】为多变量数据绘制散点图
- iText7初步使用:生成简单的pdf文件
- 移动端调试方式简记
- android studio编译c++
- css控制td内文字数量,以省略号显示