JavaWeb学习:Spring的事务管理
一、Spring的事务管理的API
①、PlatformTransactionManager:平台事务管理器
-
- 平台事务管理器:接口,是Spring用于管理事务的真正的对象。
- DataSourceTransactionManager :底层使用JDBC管理事务
- HibernateTransactionManager :底层使用Hibernate管理事务
- 平台事务管理器:接口,是Spring用于管理事务的真正的对象。
②、TransactionDefinition :事务定义信息
事务定义:用于定义事务的相关的信息,隔离级别、超时信息、传播行为、是否只读
③、TransactionStatus:事务的状态
事务状态:用于记录在事务管理过程中,事务的状态的对象。
二、事务管理的API的关系
Spring进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务的管理,在事务管理过程中,产生各种状态,将这些状态的信息记录到事务状态的对象中。
三、Spring的事务的传播行为
Spring中提供了七中事务的传播行为
public void 方法A(){ xxDao.save(); yyDao.update(); } public void 方法b(){ 方法A(); zzDao.del(); ttDao.update(); }
-
- 保证多个操作在同一个事务中
- PROPAGATION_REQUIRED:默认值,如果方法A中有事务,使用方法A中的事务,如果没有事务,创建一个新事务。
- PROPAGATION_SUPPORTS:支持事务,如果方法A中有事务,使用方法A中的事务。如果没有,不使用事务
- PROPAGATION_MANDATORY:如果方法A中有事务,使用方法A中的事务,如果没有,抛出异常
-
保证多个操作不在同一个事务中
- PROPAGATION_REQUIRES_NEW:如果方法A中有事务,将事务挂起,创建新事务,只包含自身操作。如果方法A中没有事务,创建新事务,包含自身操作。
- PROPAGATION_NOT_SUPPORTED:如果方法A中有事务,将事务挂起。不使用事务管理
- PROPAGATION_NEVER:如果方法A中有事务,抛出异常
- 嵌套式事务
- PROPAGATION_NESTED:如果方法A中有事务,按照A的事务执行,执行完成后,设置一个保存点,执行方法B中的操作,如果没有异常,执行通过,如果有异常,选择回滚到最初位置或回滚到保存点。
- 保证多个操作在同一个事务中
四、Spring的事务管理
①、搭建Spring的事务管理的环境
Ⅰ、创建Service的接口和实现类
public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void transfer(String from, String to, BigDecimal money) { accountDao.outMoney(from, money); accountDao.inMoney(to, money); } }
Ⅱ、创建DAO的接口和实现类
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao { @Override public void outMoney(String from, BigDecimal money) { this.getJdbcTemplate().update("update account set money=money - ? where name = ?", money, from); } @Override public void inMoney(String to, BigDecimal money) { this.getJdbcTemplate().update("update account set money=money + ? where name = ?", money, to); } }
Ⅲ、配置Service和DAO交给Spring管理
<bean id="accountService" class="com.xxx.spring.transaction.demo1.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> </bean> <bean id="accountDao" class="com.xxx.spring.transaction.demo1.AccountDaoImpl"> </bean>
Ⅳ、配置连接池
<context:property-placeholder location="classpath:jdbc.properties" /> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean>
Ⅴ、在DAO注入Jdbc的模板(注入的是dataSource的原因extends JdbcDaoSupport ,查看JdbcDaoSupport 的代码有setDataSource方法)
<bean id="accountDao" class="com.xxx.spring.transaction.demo1.AccountDaoImpl"> <property name="dataSource" ref="dataSource"></property> </bean>
Ⅵ、编写测试方法
@SpringJUnitConfig(locations = "classpath:tx.xml") public class SpringTxDemo { @Autowired private AccountService accountService; @Test public void demo1() { accountService.transfer("zhangsan", "lisi", new BigDecimal(1000.00)); } }
五、Spring的事务管理
①、一类:编程式事务(需要手动编写代码)
Ⅰ、配置平台事务管理器
<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" class="transactionManager"/> </bean>
Ⅲ、业务层(Service)需要使用事务,将书屋管理模板类注入到业务层
<bean id="accountService" class="com.xxx.spring.transaction.demo1.AccountServiceImpl"> <property name="accountDao" ref="accountDao"></property> <!-- 注入事务管理的模板类 --> <property name="transactionTemplate" ref="transactionTemplate"/> </bean>
②、二类:声明式事务管理(通过配置实现)---底层原理:AOP(面向切面)
在方法上通过增强的方式添加事务处理,此事务增强是环绕通知和异常抛出通知,不需要手动编写了,只需要配置就可以了
Ⅰ、XML方式的声明式事务管理
1、引入aop的开发包
2、配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
3、配置增强
<!-- 事务的增强 --> <tx:advice id="txadvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 事务规则 --> <!-- <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="find" read-only="true" /> --> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice>
在使用<tx:advice...>需要添加约束
<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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
4、AOP的配置
<!-- Aop的配置 --> <aop:config> <!-- 配置切入点 --> <aop:pointcut expression="execution(* com.xxx.spring.transaction.demo1.AccountServiceImpl.*(..))" id="pointcut1"/> <!-- 配置单一切面 --> <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"/> <!-- 配置切面 ref="aspectXML" 指定切面类--> <!-- <aop:aspect ref="aspectXML"> 前置通知 <aop:before method="checkPri" pointcut-ref="product_save" /> 后置通知 <aop:after-returning method="writeLog" pointcut-ref="product_delete" returning="result"/> 环绕通知 <aop:around method="checkPerformance" pointcut-ref="product_update"/> 异常通知 <aop:after-throwing method="afterThrowing" pointcut-ref="product_find" throwing="ex"/> 最终通知 <aop:after method="after" pointcut-ref="product_find"/> </aop:aspect> --> </aop:config>
Ⅱ、注解方式的声明式事务管理
1、引入aop的开发包
2、配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
3、开启注解事务
<tx:annotation-driven transaction-manager="transactionManager"/>
4、在业务层添加注解
@Transactional public class AccountServiceImpl implements AccountService { private AccountDao accountDao; public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; } @Override public void transfer(String from, String to, BigDecimal money) { accountDao.outMoney(from, money); int d = 1 / 0; accountDao.inMoney(to, money); } }