事务管理
目的
- 在出现异常的情况下,保证数据的一致性;数据提交操作回滚至异常发生前的状态
设计
- 项目系统设计阶段需要考虑每个功能中是否需要使用到事务
- 切忌开发过程中为了开发而开发
- 切忌在不知道为什么用事务的情况下,看到别人用自己就用
- 测试用例,开发环境或测试环境触发异常,验证是否发生回滚
方式
- Spring(Spring Framework 提供对事务管理的抽象接口) 支持两种事务管理方式:
-
编程式事务管理:使用TransactionTemplate或PlatformTransactionManager实现
- 优势:可以控制事务的粒度,最细粒度到代码块级别;
-
声明式事务管理:建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务(此处取决于事务的传播行为),在执行完目标方法之后根据执行情况提交或者回滚事务(执行成功则提交,失败则进行实物的回滚)
- 优势:在方法外进行声明,事务控制的代码不会与业务逻辑代码混在一起,最细粒度到方法级别(解决方法:可以将需要进行事务管理的代码块独立为方法,通过方法间调用实现);符合spring倡导的非侵入式的开发方式,即业务处理逻辑代码与事务管理代码不放在一起
- 分类
- 基于tx和aop名字空间的xml配置文件
- 基于注解@Transactional的声明式事务管理
-
实现
- 编程式事务管理
UserTransaction utx = entityManager.getTransaction();
try{
utx.begin();
businessLogic();
utx.commit();
}
catch(Exception ex) {
utx.rollback();
throwex;
}
- 声明式事务管理
- 基于tx和aop名字空间的xml配置文件
<!-- 拦截器方式配置事物 -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" />
<tx:method name="find*" propagation="SUPPORTS" />
<tx:method name="load*" propagation="SUPPORTS" />
<tx:method name="search*" propagation="SUPPORTS" />
<tx:method name="select*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
- 声明式事务管理
- 基于注解@Transactional的声明式事务管理
<?xml version="1.0" encoding="UTF-8"?>
<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="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 数据源tqbase-->
<bean id="dataDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
</bean>
<bean id="dataSqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="tqbaseDataSource"/>
</bean>
<bean id="dataTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataDataSource"/>
</bean>
</beans>
<!-- DataSourceTransactionManager 与 SqlSessionFactoryBean 指向同一个数据源 -->