spring的事务管理笔记

什么是事务:java

事务指的是逻辑上的一组操做,这组操做要么所有成功,要么所有失败。mysql

事务的特性:git

原子性,隔离性,一致性,持久性。spring

原子性:指的是事务是一个不可分割的工做单位,事务的发生要么所有发生,要么所有都不发生。sql

隔离性:指的是当多个用户并发访问数据库时,一个用户的事务不能被其余用户的事务所干扰,多个并发事务之间数据要相互隔离。数据库

一致性:指事务发生后,先后的数据完整性必须保持一致。express

持久性:当事务必定提交,他对数据库中的数据的改变是永久的,即便数据库发生故障也不该该对其有任何影响。编程


Spring 事务管理高层抽象主要包括了3个接口:后端

  1. platFormTransactionManager    事务管理器并发

  2. TransactionDefinition 事务定义信息(隔离,传播,超时,只读)

  3. TransactionStatus 事务具体运行状态

(1)platFormTranscationManager 是一个接口 有不少针对不一样持久层的框架去选择不一样的事务管理器

                         事务 说明
org.sprinframework.jdbc.datasource.DataSourceTransactionManager
使用Spring JDBC或iBatis进行持久化数据时使用
org.springframework.orm.hibernate3.HibernateTranscationManager 使用Hiber3.0版本进行持久化数据时使用
org.springframework.orm.jpa.JpaTranscationManager 使用JPA进行持久化时使用
org.springframework.jdo.JdoTranscationManager
当持久化机制是jdo时使用
org.springframework.transaction.jta.JtaTranscationManager 使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用

(2)TranscationDefinition

TransactionDefinition接口的常量中ISOLATION_开头的表示事物的隔离级别(4种)

没有的话隔离级别,会出现的问题:

脏读:一个事务读取到另一个事务改写但还未提交的数据。若是这些数据被回滚,则读到的数据是无效的。

不可重复读:在同一个事务中,读到了另外一个事务已经提交更新的数据返回结果不同,致使这个事务中先后的查询结果不一致。

虚读或幻读:一个事务读取一些数据以后,另外一个事务插入了一些记录,而致使这个事务中查询的数据不一致。(第二次读取,会读取到插入后一些数据)

看了上面的解释,感受不可重复读和幻读很相似。

特地查一下资料:

        不可重复读的重点在修改,你先后读取到的数据是不同。

        例子(我随便想的,可能不对):事务1,a查询卡里有1000元,事务2,有人转500到你的卡里,事务1尚未结束,它再次查询卡里的金额,显示为1500元。同一个事务中先后读取的信息不一致。

       幻读的重点在新增或删除,一样的条件, 第1次和第2次读出来的记录数不同。

        例子(网上找的):目前工资为1000的员工有10人。 事务1,读取全部工资为1000的员工。 这时另外一个事务向employee表插入了一条员工记录,工资也为1000 ,事务1再次读取全部工资为1000的员工 共读取到了11条记录,这就产生了幻像读。

隔离级别 含义
DEFAULT 使用后端数据库默认的隔离级别(spring中的选择项)
READ_UNCOMMITED 容许你读取还未提交的改变了得数据,可能致使脏读,幻读,不可重复读
READ_COMMITED 容许在并发事务已经提交读取,可防止脏读,但幻读和不可重复读仍可发生
REPEATABLE_READ 对相同字段的屡次读取是一致的,除非数据被事务自己改变。可防止脏,不可重复读,但幻读仍可发生
SERIALIZABLE 彻底服从ACID(数据库事务四要素)的隔离级别,确保不发生脏,幻,不可重复读。这在全部的隔离级别中是最慢的。他是典型的经过彻底锁定在事务中涉及的数据表完成的。

mysql默认采用REPEATABLE_READ隔离级别

oracle默认采用READ_COMMITED隔离级别

TransactionDefinition接口的常量中PROPAGATION开头的表示事物的传播行为(7种)

  当出现复杂状况时,好比某一个业务调用的业务层中的另外二个业务,每一个业务都里面都有事务。

  事务的传播行为:解决业务层方法之间的相互调用的问

事务传播行为类型 说明
PROPAGATION_REQUIRED 支持当前事务,若是不存在,就新建一个
PROPAGATION_SUPPORTS  支持当前事务,若是不存在,就不使用事务
PROPAGATION_MANDATORY  支持当前事务,若是不存在,抛出异常
PROPAGATION_REQUIRES_NEW  若是有事务存在,挂起当前事务,建立一个新的事务
PROPAGATION_NOT_SUPPORTED  以非事务运行,若是有事务存在,挂起当前事务
PROPAGATION_NEVER  以非事务运行,若是有事务存在,抛出异常
PROPAGATION_NESTED  若是当前事务存在,则嵌套事务存在

 Spring事务管理

Spring支持两种方式事务管理

--编程式的事务管理

  • 在实际应用中不多使用

  • 经过TranscationTemplate手动管理事务  

--使用xml配置声明式事务

  • 开发中推荐使用(代码侵入性最小)

  • Spring的声明式事务时经过aop实现的                                                                                                                                                                                                                                                                                 

用转帐系统的事务管理。     

  编程式的事务管理,在xml上配置:

<!-- 引入外部的属性文件 -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
	
	<!-- 配置c3p0链接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driverClass}" />
		<property name="jdbcUrl" value="${jdbc.url}" />
		<property name="user" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
	
	<!-- 配置业务层类 -->
	<bean id="accountService" class="com.spring.demo1.AccountServiceImpl">
		<property name="accountDao" ref="accountDao" />
		<!-- 注入事务管理的模板 -->
		<property name="transactionTemplate" ref="transactionTemplate" />
	</bean>
	
	<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
	<bean id="accountDao" class="com.spring.demo1.AccountDaoImpl">
		<property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类 -->
	<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
		<property name="transactionManager" ref="transactionManager"/>
	</bean>

   在转帐业务上 注入事务管理的模板   

@Override
	public void transfer(final String out, final String in, final Double money) {
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {

			@Override
			protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
				accountDao.outMoney(out, money);
				//int i = 1/0;
				accountDao.inMoney(in, money);
			}
		});
	}

基于代理的声明式的事务管理

<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- 配置业务层的代理 -->
	<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<!-- 配置目标对象 -->
		<property name="target" ref="accountService" />
		<!-- 注入事务管理器 -->
		<property name="transactionManager" ref="transactionManager" />
		<!-- 注入事务的属性 -->
		<property name="transactionAttributes">
			<props>
				<!-- 
					prop的格式:
						* PROPAGATION	:事务的传播行为
						* ISOTATION		:事务的隔离级别
						* readOnly		:只读
						* -EXCEPTION	:发生哪些异常回滚事务
						* +EXCEPTION 	:发生哪些异常不回滚事务
				 -->
				<prop key="transfer">PROPAGATION_REQUIRED</prop>
				<!-- <prop key="transfer">PROPAGATION_REQUIRED,readOnly</prop> -->
				<!-- <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop> -->
			</props>
		</property>
	</bean>

在转帐业务上 

@Override
	public void transfer(String out, String in, Double money) {
		accountDao.outMoney(out, money);
		//int i = 1/0;
		accountDao.inMoney(in, money);
	}

使用XML配置声明式的事务管理,基于tx/aop

<!-- 配置事务管理器 -->
	<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="transfer" propagation="REQUIRED"/>
			<!-- 
				propagation : 事务的传播行为
				isolation : 事务隔离级别
				read-only : 只读
				rollback-for :发生那些异常回来
				no-rollback-for : 发生哪些一场不回滚
				timeout :过时信息
			 -->
		</tx:attributes>
	</tx:advice>
	
	<!-- 配置切面 -->
	<aop:config>
		<!-- 配置切入点 -->
		<aop:pointcut expression="execution(* com.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
		<!-- 配置切面 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
	</aop:config>

业务代码

@Override
	public void transfer(String out, String in, Double money) {
		accountDao.outMoney(out, money);
		int i = 1/0;
		accountDao.inMoney(in, money);
	}

基于注解的事务管理的方式

<!-- ==================================4.基于注解的的事务管理 =============================================== -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- 开启注解事务 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

业务代码

/**
 * @Transactional 注解中的属性:
 * propagation    :事务的传播行为
 * isolation      :事务的隔离级别
 * readOnly       :只读
 * rollbackFor    :发生哪些异常回滚
 * noRollbackFor  :发生那些异常不回滚
 * @author mufeng
 *
 */
 	@Override
	public void transfer(String out, String in, Double money) {
		accountDao.outMoney(out, money);
		int i = 1/0;
		accountDao.inMoney(in, money);
	}

具体代码:http://git.oschina.net/chenfwind/spring_transcation

相关文章
相关标签/搜索