Spring事务管理--25

Spring事务管理--25

事务:指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败

事务的四大特性:

原子性:指的是事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生; 一致性:指的是事务前后数据的完整性必须保持一致; 隔离性:指的是多个用户并发访问数据库时,一个用户的事务不能被其他用户事务干扰,多个并发事务之间数据要相互隔离(通过在数据库中设置隔离级别); 持久性:指的是一个事务一旦被提交,它对数据库中数据的改变是永久性的,即使数据库发生故障也不应该对其有任何影响

Spring事务管理高层抽象主要有3个接口:

1.platform TransactionManager 平台事务管理主要是处理事务的提交,回滚等。) 2.TransactionDefinition 事务定义信息(隔离级别、传播行为、超时、只读) 3.TransactionStatus 事务具体运行状态(已经提交?是否有保存点呀?是否新的事物?) PlatformTransactionManager 根据 TransactionDefinition 进行事务管理,管理过程中事务存在多种状态,每个状态信息通过 TransactionStatus 表示


Spring为不同的持久化框架提供不同的PlatformTransactionManager接口实现


数据库事务的隔离四种隔离级别:

安全等级由小到大依次是:
    read_uncommitted     脏读、不可重复读、幻读都有可能发生
    read_committed       避免发生脏读
    repeatable_read      避免发生脏读,不可重复读
    serializble          串行的以队列的形式,都可避免
    脏读:一个事务在读取到另一个事务以改变未提交的事务,数据回滚后,可能出现无效的数据
    不可重复读:在同一个事务中,事务中前后查询的数据不一致,可能是两次查询中间有事务做了更新数据的操作。
    幻读:一个事务在查询的过程中,先后查询出的结果不一致,中间可能有另一个事务做了数据的插入

spring事务管理提供了一个isolation default ,根据持久层默认的隔离级别

oracle----read_committed mysql----repeatable_read

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

事务的传播行为有七种,又分为三类:第一类共同点:如果 A 方法中有事务,则调用 B 方法时就用该事务,即:A和B方法在同一个事务中。PROPAGATION_REQUIRED:如果 A 方法中没有事务,则调用 B 方法时就创建一个新的事务,即:A和B方法在同一个事务中。PROPAGATION_SUPPORTS:如果 A 方法中没有事务,则调用 B 方法时就不使用该事务。PROPAGATION_MANDATORY:如果 A 方法中没有事务,则调用 B 方法时就抛出异常。第二类共同点:A方法和B方法没有在同一个事务里面。PROPAGATION_REQUIRES_NEW:如果 A 方法中有事务,则挂起新建一个事务给 B 方法。PROPAGATION_NOT_SUPPORTED:如果 A 方法中有事务,则挂起。PROPAGATION_NEVER:如果 A 方法中有事务,则报异常。第三类:如果 A 方法有的事务执行完,设置一个保存点,如果 B 方法中事务执行失败,可以滚回保存点初始状态
PROPAGATION_NESTED :如果当前事务存在,则嵌套事务执行
@重点的三种:PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW, PROPAGATION_NESTED。
==================================================================================================================================

TransactionStatus接口用来记录事务的状态

该接口定义了一组方法,用来获取或判断事务的相应状态信息. 平台事务管理器(PlatformTransactionManager)会根据TransactionDefinition中定义的事务信息(包括隔离级别、传播行为)来进行事务的管理,在管理的过程中事务可能产生了保存点或事务是新的事务等情况,那么这些信息都会记录在TransactionStatus的对象中.


============================================================================================================================
 

Spring事务管理

Spring 支持两种方式事务管理

(1)编程式的事务管理

1、在实际应用中很少使用 2、通过 TransatcionTemplate 手动管理

(2)使用 XML 配置声明式事务

1、开发中推荐使用(代码侵入性最小) 2、Spring 的声明式事务是通过AOP实现的

转账案例:


编程式的事务控制

配置事务管理器:TranscationManager,一般在不适用Hibernate的情况下,使用DataSourceTranscationManager,需要注入数据源 ②配置事务管理器的管理事务的模板,如果不配置,需要手动编程事务管理的方法,很麻烦,建议使用spring提供的事务模板方法:transcationTemplate,需要注入事务管理器 ③将TranscationTempalte配置好后,注入到使用的事务的service层的类中,作为属性。 ④在service中,执行transcationTemplate提供的execute方法,方法中进行事务的操作,这个方法中有个参数,transcationcallback,如果事务出现回滚,将会调用这个参数进行操作。

<!-- ==================================1.编程式的事务管理=============================================== -->
	<!-- 配置事务管理器 -->
	<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>

public class AccountServiceImpl implements AccountService {
	
	//注入转账的DAO
	private AccountDao accountDao;
	//注入事务管理的模板
	private TransactionTemplate transactionTemplate;

	/**
	 * @param out	:转出账号
	 * @param in	:转入账号
	 * @param money	:转账金额
	 */
	@Override
	public void transfer(final String out, final String in, final Double money) {
		/*accountDao.outMoney(out, money);
		//int i = 1/0;
		accountDao.inMoney(in, money);*/
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
				accountDao.outMoney(out, money);
				//int i = 1/0;
				accountDao.inMoney(in, money);
			}
		});
	}

基于TransactionProxyFactoryBean的声明式事务管理的方式

这种方式只是简单的使用到了aop的思想,对service对象进行了代理模式的增强,前一章在编程式事务管理器的时候需要在service中注入事务管理器的模板,而现在这种声明式的方法,配置了TransactionProxyFactoryBean,属性对象之一就是原先的service,这就是对目标对象进行代理,除了引用transactionManager之外还需要声明事务的属性,也就是隔离级别、传播行为、是否只读、异常处理等等。

声明式的事务管理(传统方式)
声明式的事务管理是基于AOP的思想完成的.因此需要引用Spring AOP开发需要用到的jar包.
传统的声明式事务管理:

1.配置事务管理器

<!-- ==================================2.使用XML配置声明式的事务管理(原始方式)=============================================== -->
	
	<!-- 配置事务管理器 -->
	<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>
		<!-- 注入事务的属性 -->
		<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>

</beans>

2.引用TransactionProxyFactoryBean,TransactionProxyFactoryBean是采用动态代理完成事务管理的,直接配置一个TransactionProxyFactoryBean即可.

 
TransactionProxyFactoryBean中有4个属性,分别是proxyInterfaces、target、transactionManager、transactionAttributes属性.
proxyInterfaces:该属性配置需要代理的接口
target:该属性配置proxyInterfaces中指定接口的实现类
transactionManager:该属性指定一个TransactionManager
transactionAttributes:该属性指定需要设置proxyInterfaces的接口中需要添加事务的的方法.支持<props>多个配置.因为此属性是Properties类型(java.util.Properties).此类型是键值对的形式.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class TransactionTest {

	/**
	 * 一定要注入代理类:因为代理类进行增强的操作
	 */
	//@Resource(name="accountService")
	@Resource(name="accountServiceProxy")
	private AccountService accountService;
	
	@Test
	public void demo1(){
		accountService.transfer("aaa", "bbb", 200d);
	}
}

基于aspectj(切面)配置

这是一种经常使用的事务声明方式 在配置文件中配置完dataSourceTransactionManager之后,使用spring提供的命名空间为<tx:advice>的标签给事务配置属性,比如传播行为、隔离级别、异常处理等等,这是一种基于面向切面的配置方式,可以在任何想要事务处理的地方使用,其次就是使用aop的声明式方式完成advicepointcut的横切面配置,注意advice引用的就是<tx>标签配置的事务pointcut是切入的方法

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

</beans>

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class TransactionTest {

	/**
	 * 一定要注入代理类:因为代理类进行增强的操作
	 */
	@Resource(name="accountService")
	private AccountService accountService;
	
	@Test
	public void demo1(){
		accountService.transfer("aaa", "bbb", 200d);
	}
}


基于注解的声明式事务管理方式:

配置完事务管理器之后,只需要在配置文件中使用<tx:annotation-driver transactionManager=“transactionManager”>
将基于事务注解的方式打开,
在需要注解管理的类上添加@Transactional
以达到控制事务的目的

<!-- ==================================4.使用注解配置声明式事务============================================ -->

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

/**
 * @author admin
 *@Transactional中的的属性
 *propagation	:事务的传播行为
 *isolation		:事务的隔离级别
 *readOnly		:只读
 *rollbackFor	:发生哪些异常回滚
 *noRollbackFor	:发生哪些异常不回滚
 *rollbackForClassName 根据异常类名回滚
 */
@Transactional
public class AccountServiceImpl implements AccountService {
	
	//注入转账的DAO
	private AccountDao accountDao;
	/**
	 * @param out	:转出账号
	 * @param in	:转入账号
	 * @param money	:转账金额
	 */
	@Override
	public void transfer( String out, String in, Double money) {
		accountDao.outMoney(out, money);
		//int i = 1/0;
		accountDao.inMoney(in, money);
		
	}

	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}

}


spring事务管理的几种实现方式:

1:编程式的事务管理 手动为每个事务管理的类编写增强的代码(基本上不用) 2:声明式的事务管理 一:基于transctionProxyFactoryBean的事务管理 基本上不用,要为每个业务层的类配置事务属性,不利于代码的维护 二:基于AspectJ的XML的声明式事务管理 是整合AOP的方式,以tx:adcvice的方式配置 配置切入点跟切入面。 企业级应用开发中使用较多。 三:基于spring注解的方式 配置简单,只需要开启spring的注解驱动,以annotion的方式,但是需要在每个业务层的类加上tansctional的注解。 里面配置事务的相关行为属性, 用的也多。 spring的四种注入方式: 1:set方法注入 2:构造器注入 3:工厂方法的注入 4:抽象工厂方法的注入 大多数情况下用前面两种,注意事项: spring容器创建的对象默认为单例,如果需要多实例的类,则在bean属性里面配置一个scope="prototype"的属性























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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值