Spring的事务管理

一、Spring为事务管理提供了三个接口:

1)PlatformTransactionManager:事务管理器,涵盖了事务提交,回滚等操作信息,spring为不同的持久化框架提供了不同的PlatformTransactionManager接口实现

2)TransactionDefinition:事务定义信息,涵盖了隔离级别、传播行为、超时、只读等操作信息。

3)Transactionstatus:事务具体运行状态,isNewTransaction() hasSavePoint()等等


二、TransactionDefinition的介绍

1)如果不考虑隔离性会引发的安全问题:脏读、不可重复读、幻读
脏读:一个事务读取到了另一个事务改了但还没提交数据,如果这些数据被回滚,则读到的是无效的数据。
不可重复读:一个事务读到另一个事务更新提交了的数据,导致在这个事务中,多次读取同一数据返回的结果有所不同。


2)事务的隔离级别:ISOLATION_...

隔离级别含义
DEFAULT使用后端数据库默认的隔离级别
READ_UNCOMMITED允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读
READ_COMMITED允许在并发事务提交后读取。可以防止脏读,但幻、不可重复读仍可发生
REPEATABLE_READ对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,仍可发生幻读
SERIALIZABLE完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。在所有的隔离级别中是最慢的

3)事务的传播行为:事务的传播行为:PROPAGATION_...

1: PROPAGATION_REQUIRED 
假如当前正要执行的事务不在另外一个事务里,那么就起一个新的事务。
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,
 ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA
的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被
提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚


2:   PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行。

比如说ServiceA.methodA没有事务,那么ServiceB.methodB也不会创建事务。


3:   PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。


4:   PROPAGATION_REQUIRES_NEW
这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,
他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在
两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,
如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。


5:   PROPAGATION_NOT_SUPPORTED 
当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。


6:   PROPAGATION_NEVER 
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,
那么ServiceB.methodB就要抛出异常了。


7:   PROPAGATION_NESTED 
理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,
而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
而Nested事务的好处是他有一个savepoint。


三、事务管理的分类:

1)编程式事务管理:

*手动编写代码进行事务管理。(很少使用)

2)声明式事务管理:

*基于TransactionProxyFactoryBean的方式。(很少使用:因为需要为每个进行事务管理的类配置一个TransactionProxyFactoryBean进行增强)

*基于AspectJ的XML方式。(经常使用:一旦配置好之后,类上不需要添加任何东西)

*基于注解方式(经常使用:配置简单,但需要在业务层类上添加一个@Transactional的注解)


3)基于AspectJ的XML方式的配置

*首先在applicationContext.xml引入tx和aop的命名空间

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd


*引入两个jar包:spring-aspectjs-3.2.0.RELEASE.jar、com。springsource.org.aspectj.weaver-1.6.8.RELEASE.jar


*在applicationContext.xml配置

     <!-- 事务管理配置 -->
     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="dataSource" ref="dataSource" />
     </bean>

    <!-- 配置事务的通知(事务的增强) -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    	<tx:attributes>
    		<tx:method name="update*" propagation="REQUIRED"/>
    	</tx:attributes>
    </tx:advice>

   <!-- 配置切面 -->
   <aop:config>
   	<!-- 配置切入点 -->
   	<aop:pointcut id="pointcut1" expression="excction(* com.yangjf.service.*(..))" id=""/>
   	<!-- 配置切面 -->
   	<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
   </aop:config>

4)使用基于注解配置声明式事务

*在applicationContext.xml文件配置

        <context:property-placeholder location="classpath:/hibernate.properties" />

        <!-- 连接池配置 -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${dataSource.driverClassName}" />
		<property name="url" value="${dataSource.url}" />
		<property name="username" value="${dataSource.username}" />
		<property name="password" value="${dataSource.password}" />
	</bean>

        <!-- 事务管理配置 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

        <tx:annotation-driven transaction-manager="transactionManager" />



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值