Spring - 14 Spring框架的事务管理

124 篇文章 1 订阅
96 篇文章 0 订阅

 

 

 

 

  • 通过手动编写代码的方式完成事务的管理

 

1.配置DataSourceTransactionManager事务管理器传入数据库连接池属性dataSource

2.配置TransactionTemplate事务模板传入事务管理器属性DataSourceTransactionManager

3.在需要使用事务的类中注入事务模板

4.使用事务模板的execute方法传入回调函数TransactionCallbackWithoutResult接口的匿名内部类或实现类

5.实现TransactionCallbackWithoutResult接口的方法doInTransactionWithoutResult将业务逻辑丢到里面即可

配置文件

<?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: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.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.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">
	
	<!-- 手动完成事务管理 -->
	
	
	<!-- 配置datasource C3P0 属性name值与JDBC不同需要注意-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="com.mysql.jdbc.Driver"/>
    	<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
    	<property name="user" value="root"/>
    	<property name="password" value="Aa123456"/>
    </bean>
	
	<!-- 注入dataSource,持久层继承jdbcdaosupport,这里只传连接池就可以 -->
	<bean id="accountDao" class="demo1.AccountDaoImpl">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 注入dao -->
	<bean id="accountService" class="demo1.AccountServiceImpl">
		<property name="accountDao" ref="accountDao"/>
	</bean>
	
	<!-- 配置事务管理器,注入数据库连接池 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>	
	<!-- 配置事务模板,注入事务管理器 -->
	<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
		<property name="transactionManager" ref="transactionManager"></property>
	</bean>
	
	
	
</beans>

 

需使用事务的类

package demo1;

import javax.annotation.Resource;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

public class AccountServiceImpl implements AccountService {

	
	private AccountDao accountDao;
	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
	
	
	/**
	 * #演示手动处理事务
	 */
	@Resource(name="transactionTemplate")
	private TransactionTemplate transactionTemplate;
	
	
	public void pay1(String out, String in, double money) {
		//执行TransactionTemplate.execute方法回调接口使用TransactionCallbackWithoutResult匿名内部类
		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			//将执行逻辑放入接口的实现方法中
			@Override
			protected void doInTransactionWithoutResult(TransactionStatus arg0) {
				//执行逻辑
				accountDao.outMoney(out, money);
				//模拟异常
				int i = 1 / 0;
				accountDao.inMoney(in, money);				
			}
		});
		

		
	}
	
	
}

测试类
 

package demo1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration("classpath:applicationContext2.xml")
public class Demo {

	@Resource(name="accountService")
	private AccountService accountService;

	/*
	 *	测试手动处理事务
	 */
	@Test
	public void run2() {
		accountService.pay1("alex", "alex1", 10000);
	}

	
}

junit报错

 

数据库没有变化

事务开启成功。

       

  • Spring的声明式事务管理,通过一段配置的方式完成事务的管理(底层采用AOP的技术)。

1.Spring框架的事务管理之基于AspectJ的XML方式

1)配置事务管理器

2)配置事务的隔离级别与传播行为常量

这里有些简介可以参考:

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. 事务的传播行为常量(不用设置,使用默认值)
	* 先解释什么是事务的传播行为:解决的是业务层之间的方法调用!!
	
	* 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出现异常,运行客户根据需求回滚(选择回滚到保存点或者是最初始状态)

3)配置AOP的切面

4)完整配置文件

<?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: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.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.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">
	
	<!-- 配置datasource C3P0 属性name值与JDBC不同需要注意-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="com.mysql.jdbc.Driver"/>
    	<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
    	<property name="user" value="root"/>
    	<property name="password" value="Aa123456"/>
    </bean>
	
	<!-- 注入dataSource,持久层继承jdbcdaosupport,这里只传连接池就可以 -->
	<bean id="accountDao" class="demo1.AccountDaoImpl">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 注入dao -->
	<bean id="accountService" class="demo1.AccountServiceImpl">
		<property name="accountDao" ref="accountDao"/>
	</bean>
	
	
	<!-- Spring框架的事务管理之基于AspectJ的XML方式 -->
	
	
	<!-- 配置事务管理器 -->
	<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属性:方法名
					isolation属性:隔离级别
					propagation:传播行为
			-->
			<tx:method name="pay2" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 配置AOP切面 -->
	<aop:config>
		<!-- 
			aop:advisor标签 配置spring提供的advice(通知)
			advice-ref属性传入自己定义的tx:advice
		 -->
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* *..*.pay2(..))"/>
		<!-- 
			aop:aspect标签配置自己定义的切面
			<aop:aspect></aop:aspect>
		 -->
	</aop:config>
	
	
	
	
</beans>

5)serviceImpl与测试类


public class AccountServiceImpl implements AccountService {

	
	private AccountDao accountDao;
	public void setAccountDao(AccountDao accountDao) {
		this.accountDao = accountDao;
	}
	
	
	/**
	 * #演示Spring框架的事务管理之基于AspectJ的XML方式
	 */
	public void pay2(String out, String in, double money) {
		accountDao.outMoney(out, money);
		//模拟异常
		int i = 1 / 0;
		accountDao.inMoney(in, money);				
	}
	
}

 

package demo1;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")
@ContextConfiguration("classpath:applicationContext3.xml")
public class Demo {

	@Resource(name="accountService")
	private AccountService accountService;
	/*
	 *	Spring框架的事务管理之基于AspectJ的XML方式
	 */
	@Test
	public void run3() {
		accountService.pay2("alex", "alex1", 10000);
	}
	
}

 

2.Spring框架的事务管理之基于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

4)完整配置文件

<?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: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.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.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">
	
	<!-- 配置datasource C3P0 属性name值与JDBC不同需要注意-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    	<property name="driverClass" value="com.mysql.jdbc.Driver"/>
    	<property name="jdbcUrl" value="jdbc:mysql:///spring_day03"/>
    	<property name="user" value="root"/>
    	<property name="password" value="Aa123456"/>
    </bean>
	
	<!-- 注入dataSource,持久层继承jdbcdaosupport,这里只传连接池就可以 -->
	<bean id="accountDao" class="demo1.AccountDaoImpl">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 注入dao -->
	<bean id="accountService" class="demo1.AccountServiceImpl">
		<property name="accountDao" ref="accountDao"/>
	</bean>
	
	
	<!-- Spring框架的事务管理之基于AspectJ的注解方式 -->
	
	<!-- 配置事务管理器,传入datasource -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
	<!-- 开启注解事务 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
	
	
	
	
</beans>

 

5)测试类


@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration("classpath:applicationContext4.xml")
public class Demo {

	@Resource(name="accountService")
	private AccountService accountService;

	/*
	 *	Spring框架的事务管理之基于AspectJ的注解方式
	 */
	@Test
	public void run4() {
		accountService.pay2("alex", "alex1", 10000);
	}
	
}

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值