Spring的事务管理机制

一、数据库事务

数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。

事务的四个关键属性(ACID):

1原子性(atomicity):事务是一个原子操作, 由一系列动作组成.事务的原子性确保动作要么全部完成要么完全不起作用.

2一致性(consistency):一旦所有事务动作完成, 事务就被提交.数据和资源就处于一种满足业务规则的一致性状态中.

3隔离性(isolation):可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来,防止数据损坏.

4持久性(durability):一旦事务完成, 无论发生什么系统错误,它的结果都不应该受到影响.通常情况下,事务的结果被写到持久化存储器中.

二、Spring支持两种类型的事务管理:

作为企业级应用程序框架, Spring 在不同的事务管理 API 之上定义了一个抽象层.而应用程序开发人员不必了解底层的事务管理 API,就可以使用 Spring的事务管理机制.

编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。

声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。

声明式事务管理

声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

声明式事务管理也有两种常用的方式,一种是基于txaop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

(1)基于txaop名字空间的xml配置文件

事务管理是一种横切关注点

为了在 Spring 2.x 中启用声明式事务管理,可以通过 tx Schema中定义的 <tx:advice>元素声明事务通知,为此必须事先将这个 Schema定义添加到 <beans>根元素中去.

声明了事务通知后, 就需要将它与切入点关联起来.由于事务通知是在 <aop:config>元素外部声明的,所以它无法直接与切入点产生关联.所以必须在 <aop:config>元素中声明一个增强器通知与切入点关联起来.

由于 Spring AOP 是基于代理的方法,所以只能增强公共方法.因此, 只有公有方法才能通过 Spring AOP进行事务管理.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
	
	<context:component-scan base-package="com.spring"></context:component-scan>
	
	<!-- 导入资源文件 -->
	<context:property-placeholder location="classpath:db.properties"/>
	
	<!-- 配置 C3P0 数据源 -->
	<bean id="dataSource"
		class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="driverClass" value="${jdbc.driverClass}"></property>

		<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
		<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
	</bean>
	
	<!-- 配置 Spirng 的 JdbcTemplate -->
	<bean id="jdbcTemplate" 
		class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 配置 bean -->
	<bean id="bookShopDao" class="com.spring.BookShopDaoImpl">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>
	
	<bean id="bookShopService" class="com.spring.BookShopServiceImpl">
		<property name="bookShopDao" ref="bookShopDao"></property>
	</bean>
	
	<bean id="cashier" class="com.spring.CashierImpl">
		<property name="bookShopService" ref="bookShopService"></property>
	</bean>
	
	<!-- 1. 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 2. 配置事务属性 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- 根据方法名指定事务的属性 -->
			<tx:method name="purchase" propagation="REQUIRES_NEW"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="find*" read-only="true"/>
			<tx:method name="*"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 -->
	<aop:config>
		<aop:pointcut expression="execution(* com.spring.*.*(..))" 
			id="txPointCut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>	
	</aop:config>
	
</beans>


(2)基于@Transactional注解

为了将方法定义为支持事务处理的, 可以为方法添加@Transactional 注解.根据 Spring AOP基于代理机制,只能标注公有方法.

可以在方法或者类级别上添加 @Transactional 注解.当把这个注解应用到类上时,这个类中的所有公共方法都会被定义成支持事务处理的.

Bean 配置文件中只需要启用<tx:annotation-driven> 元素,并为之指定事务管理器就可以了.

如果事务处理器的名称是 transactionManager, 就可以在<tx:annotation-driven>元素中省略 transaction-manager属性. 这个元素会自动检测该名称的事务处理器.

	<!-- 配置 Spirng 的 JdbcTemplate -->
	<bean id="jdbcTemplate" 
		class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
<!--  配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<context:component-scan base-package="org.simpleit.transaction_1"/>
<tx:annotation-driven/>




猜你喜欢

转载自blog.csdn.net/snow_7/article/details/52116920