Spring事务管理

1. Spring框架的事务管理

1. PlatformTransactionManager接口	-- 平台事务管理器.(真正管理事务的类)。该接口有具体的实现类,根据不同的持久层框架,需要选择不同的实现类!
2. TransactionDefinition接口			-- 事务定义信息.(事务的隔离级别,传播行为,超时,只读)
3. TransactionStatus接口				-- 事务的状态

4. 总结:上述对象之间的关系:平台事务管理器真正管理事务对象.根据事务定义的信息TransactionDefinition 进行事务管理,在管理事务中产生一些状态.将状态记录到TransactionStatus中

5. PlatformTransactionManager接口中实现类和常用的方法
	1. 接口的实现类
		* 如果使用的Spring的JDBC模板或者MyBatis框架,需要选择DataSourceTransactionManager实现类
		* 如果使用的是Hibernate的框架,需要选择HibernateTransactionManager实现类
	
	2. 该接口的常用方法
		* void commit(TransactionStatus status) 
		* TransactionStatus getTransaction(TransactionDefinition definition) 
		* void rollback(TransactionStatus status) 

6. TransactionDefinition
	1. 事务隔离级别的常量
		* static int ISOLATION_DEFAULT 					-- 采用数据库的默认隔离级别
		* static int ISOLATION_READ_UNCOMMITTED 
		* static int ISOLATION_READ_COMMITTED 
		* static int ISOLATION_REPEATABLE_READ 
		* static int ISOLATION_SERIALIZABLE 
	
	2. 事务的传播行为常量
		* 先解释什么是事务的传播行为:解决的是业务层之间的方法调用!!
		A、B代表业务层的两个事务方法
		* PROPAGATION_REQUIRED(默认值)	-- A中有事务,使用A中的事务.如果没有,B就会开启一个新的事务,将A包含进来.(保证A,B在同一个事务中),默认值!!
		* PROPAGATION_SUPPORTS			-- A中有事务,使用A中的事务.如果A中没有事务.那么B也不使用事务.
		* PROPAGATION_MANDATORY			-- A中有事务,使用A中的事务.如果A没有事务.抛出异常.
		
		* PROPAGATION_REQUIRES_NEW		-- A中有事务,将A中的事务挂起.B创建一个新的事务.(保证A,B没有在一个事务中)
		* PROPAGATION_NOT_SUPPORTED		-- A中有事务,将A中的事务挂起.
		* PROPAGATION_NEVER 			-- A中有事务,抛出异常.
		
		* PROPAGATION_NESTED			-- 嵌套事务.当A执行之后,就会在这个位置设置一个保存点.如果B没有问题.执行通过.如果B出现异常,运行客户根据需求回滚(选择回滚到保存点或者是最初始状态)

2. Spring框架的事务管理的分类

Spring的事务管理的分类
	1. Spring的编程式事务管理(不常用)
		* 通过手动编写代码的方式完成事务的管理
	
	2. Spring的声明式事务管理
		* 通过一段配置的方式完成事务的管理

2.1 编程式的事务管理

1. 说明:Spring为了简化事务管理的代码:提供了模板类 TransactionTemplate,所以手动编程的方式来管理事务,只需要使用该模板类即可!!

2. 手动编程方式的具体步骤如下:
	1. 步骤一:配置一个事务管理器,Spring使用PlatformTransactionManager接口来管理事务,所以咱们需要使用到他的实现类!!
		<!-- 配置事务管理器 -->
		<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
			<property name="dataSource" ref="dataSource"/>
		</bean>
	
	2. 步骤二:配置事务管理的模板
		<!-- 配置事务管理的模板 -->
		<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
			<property name="transactionManager" ref="transactionManager"/>
		</bean>
	
	3. 步骤三:在需要进行事务管理的类中,注入事务管理的模板.
		<bean id="accountService" class="com.yp.demo1.AccountServiceImpl">
			<property name="accountDao" ref="accountDao"/>
			<property name="transactionTemplate" ref="transactionTemplate"/>
		</bean>
	
	4. 步骤四:在业务层使用模板管理事务:
		// 注入事务模板对象
		private TransactionTemplate transactionTemplate;
		public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
		}

		public void pay(final String out, final String in, final double money) {
			transactionTemplate.execute(new TransactionCallbackWithoutResult() {
	
				protected void doInTransactionWithoutResult(TransactionStatus status) {
					// 扣钱
					accountDao.outMoney(out, money);
		
					// 加钱
					accountDao.inMoney(in, money);
				}
			});
		}

2.2 声明式事务管理

 声明式事务管理又分成两种方式
	* 基于AspectJ的XML方式
	* 基于AspectJ的注解方式
2.2.1 基于AspectJ的XML方式(JDBCTemplate)
1. 步骤一:配置事务管理器
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>

2. 步骤二:配置事务增强
	<!-- 配置事务增强 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!--
				name		:绑定事务的方法名,可以使用通配符,可以配置多个。
				propagation	:传播行为
				isolation	:隔离级别
				read-only	:是否只读
				timeout		:超时信息
				rollback-for:发生哪些异常回滚.
				no-rollback-for:发生哪些异常不回滚.
			 -->
			<!-- 哪些方法加事务 -->
			<tx:method name="save*" propagation="REQUIRED"/>
			<tx:method name="insert*" propagation="REQUIRED"/>
		
			<tx:method name="delete*" propagation="REQUIRED"/>
		
			<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
			<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
			<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
		
			<tx:method name="update*" propagation="REQUIRED"/>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>

3. 步骤三:配置AOP的切面
	<!-- 配置AOP切面产生代理 -->
	<aop:config>
		<aop:pointcut expression="execution(* com.yichangapp.*.service.*Impl.*(..))" id="txPointCut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
	</aop:config>
2.2.2 基于AspectJ的注解方式
1. 步骤一:配置事务管理器
	<!-- 配置事务管理器  -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>

2. 步骤二:开启注解事务
	<!-- 开启注解事务 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

3. 步骤三:在业务层上添加一个注解:@Transactional

3. 常用持久化框架配置

3.1 MyBatis配置

sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<!-- 全局setting配置,根据需要添加 -->
	
	<!-- 批量别名定义,扫描整个包下的类,首字母大写小写都可以,但程序可读性差 
	<typeAliases>
		<package name="com.yichangapp.po"/>
	</typeAliases>-->
</configuration>

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.2.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
		
	<!-- 加载数据库参数配置文件 -->
	<context:property-placeholder location="classpath:db.properties" />
	
	<!-- c3p0数据库连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}"/>
		<property name="jdbcUrl" value="${jdbc.url}"/>
		<property name="user" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		<!-- 还可以继续设置其他参数
			...	-->
	</bean>
	
	<!-- sqlSession的工厂类sqlSessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 注入sql映射的配置文件 -->
		<property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml"/>
		<!-- 注入数据源 -->
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!-- mapper扫描器配置,直接将所扫描的包下的Mapper注入IOC容器 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 扫描包配置,如果需要配置多个包,使用半角逗号隔开 -->
		<property name="basePackage" value="com.yichangapp.mine.mapper"/>
		<!-- 注意这里是value,不是ref -->
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
	</bean>

	<!-- Mybatis使用jdbc的事务控制器 -->
	<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="save*" propagation="REQUIRED"/>
			<tx:method name="insert*" propagation="REQUIRED"/>
			
			<tx:method name="delete*" propagation="REQUIRED"/>
			
			<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
			<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
			<tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
			
			<tx:method name="update*" propagation="REQUIRED"/>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- spring AOP 管理事务 -->
	<aop:config>
		<aop:pointcut expression="execution(* com.yichangapp.*.service.*Impl.*(..))" id="txPointCut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
	</aop:config>
</beans>

3.2 Hibernate配置

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

	<session-factory>
		<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>

		<property name="show_sql">true</property>
		<property name="format_sql">true</property>
		<property name="hbm2ddl.auto">none</property>
		<!-- 懒加载,配合web.xml中配置的 openSessionInViewFilter -->
		<property name="hibernate.enable_lazy_load_no_trans">true</property>
        <!--校验模式  JPA  java persistent api-->
		<property name="javax.persistence.validation.mode">none</property>
		
		<!--  加载映射文件-->
		<mapping resource="com/yichangapp/domain/Dept.hbm.xml"></mapping>
		<mapping resource="com/yichangapp/domain/User.hbm.xml"></mapping>
	</session-factory>
</hibernate-configuration>

applicationContext.xml

<?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:p="http://www.springframework.org/schema/p"
	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/beans    
	http://www.springframework.org/schema/beans/spring-beans.xsd    
	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    
	http://www.springframework.org/schema/context    
	http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- c3p0数据源连接Oracle数据库 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
		<property name="jdbcUrl" value="jdbc:oracle:thin:@192.168.110.131:1521:orcl" />
		<property name="user" value="yypp" />
		<property name="password" value="xxxxx" />
	</bean>

	<!-- 加载hibernate.cfg.xml,注入dataSource获取session工厂 -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:hibernate.cfg.xml" />
	</bean>

	<!-- 获取链接来管理事务,可以认为AOP将要织入的增强 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate5.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!-- 通知或称增强,以及将要增强那些方法或可以说那些方法加事务 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="save*" propagation="REQUIRED" />
			<tx:method name="insert*" propagation="REQUIRED" />
			<tx:method name="update*" propagation="REQUIRED" />
			<tx:method name="delete*" propagation="REQUIRED" />
			<tx:method name="get*" read-only="true" />
			<tx:method name="*" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>

	<!-- AOP切面,即 通知 + 切入点 其实有时候目录很难组织事务管理,可以配置多个pointcut -->
	<aop:config>
		<aop:pointcut expression="execution(* com.yichangapp.*.service.*Impl.*(..))" id="txPointCut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
	</aop:config>

	<!-- 导入其他模块的spring配置文件 -->
	<import resource="classpath:applicationContext-dao.xml" />
	<import resource="classpath:applicationContext-service.xml" />
</beans>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值