-
通过手动编写代码的方式完成事务的管理
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);
}
}