Spring 事务管理
事务的概念:生产环境中一次业务需求需要对数据库进行多次修改,这些修改要么全部成功,要么全部失败,这称为事务。
Spring 事务管理是什么 ?
Spring 事务管理是由Spring框架来管理事务的回滚等操作。
它为什么而存在,或者说它可以干什么
用JDBC、Hibernate等底层事务管理都可以实现事务管理,规模小事务管理比较方便,一旦事务规模扩大,管理上将会造成困难。而且两种接口并不兼容,如果需要替换,将会很麻烦。Spring将他们封装起来,具有统一的事务编程模型。替换底层的事务管理将不会影响项目。Spring 事务管理实现了编程式事务及声明式事务(AOP)
一、底层事务管理
JDBC
try{
connection。setAutoCommit(false)
//dowork
connection.commit();
} catch(Exception e){
connection.rollback();
} finally{
connection.close();
}
Hibernate
Session sesslon = factory.openSession();
Transaction tx = nu11;
try{
tx=session.beginTransaction();
//dowork
tx.commit();
}catch(RuntimeException e){
if(tx != null){
tx.rollback();
}
}finaIIy{
session。close():
}
二、接口
事务接口
事务接口抽象出三个功能
- 获取事务
- 提交事务
- 回滚事务
public interface PlatformTransactionManager{
TransactionStatus getTransaction(
TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatusstatus)throws TransactionException;
void rollback(TransactionStatusstatus)throws TransactionException;
实现
封装JDBC事务:DataSourceTransactionManager类实现PlatformTransactionManager接口
封装Hibernate事务:HibernateTransactionManager类实现PlatformTransactionManager接口
事务定义
TransactionDefinition
属性 | 含义 |
---|---|
getName | 事务名称 |
getIsolationLevel | 隔离级别 |
getPropagationBehavior | 传播行为 |
getTimeout | 超时时间 |
isReadOnly | 是否只读事务 |
事务状态
属性 | 含义 |
---|---|
isNewTransaction | 是否是新的事务 |
hasSavepoint | 是否有savepoint(诊断,NESTED) |
isCompleted | 是否已完成 |
isRollbackOnly | 事务结果是否是rollback-only |
setRollbackOnly | 设置事务为rollback-only(Transaction) |
隔离级别
属性 | 含义 |
---|---|
ISOLATION_READ_UNCOMMITTED | 读未提交 |
ISOLATION_READ_COMMITTED | 读提交 |
ISOLATION_REPEATABLE_READ | 重复读 |
ISOLATION_SERIALIZABLE | 串行化 |
ISOLATION_DEFAULT | 默认 |
传播行为
传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
class DaoA {
public void transactionA(){
doSomeWork();
}
}
class DaoB {
publicvoidtransactionB(){
daoA,transactionA();
doSomeOtherWork();
}
}
属性 | 含义 | 底层实现 |
---|---|---|
PROPAGATION_MANDATORY | 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常 | |
PROPAGATION_NEVER | 总是非事务地执行,如果存在一个活动事务,则抛出异常。 | |
PROPAGATION_NOT_SUPPORTED | 总是非事务地执行,并挂起任何存在的事务。 | |
PROPAGATION_SUPPORTS | 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。 | |
PROPAGATION_REQUIRED | 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 | 内部事务会影响外部事务 |
PROPAGATION_NESTED | 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。(同上,区别在底层实现上) | 事务之间相互不影响(savepoints) |
PROPAGATION_ REQUIRED_NEW | 必须在新事物中执行,挂起当前事务 | 独立physical事务 |
注:内部事务会影响外部事务:指事务A包含事务B,如果事务B回滚,那么事务也要回滚。
三、事务式声明
声明式事务是建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
—摘自Spring的编程式事务和声明式事务 作者:nnngu
- 添加 schema
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
- 定义事务管理器(此处采用的是JDBC的事务管理器)
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="db.properties"/>
- 定义事务Advice(AOP需要)
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="transfer*"/>
</tx:attributes>
</tx:advice>
- 定义Pointcut (AOP需要)
<aop:config>
<aop:pointcut id="daoOperation" expression="execution(* com.netease.course.AccountDao.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoOperation"/>
</aop:config>
- 配置< tx:method/ >
属性 | 含义 |
---|---|
Name | 匹配的函数名称,支持*匹配 |
Propagation | 事务传播行为 |
Isolation | 事务隔离级别 |
timeout | 超时 |
read-only | 是否只读事务 |
rollback-for | 触发回滚的异常,都好分隔 |
no-rollback-for | 不触发回滚的异常,逗号分隔 |
注解配置事务@Transaction
XML配置
<tx:annotation-driven transaction-manager="txManager"/>
示例
@Transactional(propagation=Propagation.REQUIRED, rollbackFor = Exception.class)
public bool eandeleteCtusterByC1usterId(Stringclusterld){
//dowork
}
@Transactional的配置属性
属性 | 含义 |
---|---|
value | 使用的TransactionManager |
propagation | 事务传播行为 |
isolation | 事务隔离级别 |
timeout | 超时 |
read-only | 是否只读事务 |
rollbackFor | 触发回滚的异常类对象数组 |
rollbackForClassName | 触发回滚的异常类名称数组 |
noRollbackFor | 不触发回滚的异常类对象数组 |
noRollbackForClassName | 不触发回滚的异常类名称数组 |
四、编程式事务
编程式事务使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
—摘自Spring的编程式事务和声明式事务 作者:nnngu
TransactionTemplate
TransactionTemplate是Spring封装的PlatformTransactionManager。
TransactionTemplate通过把事务的相关操作,作为回调的方式,返回给用户。用户在回调中写相关操作即可。无需担心在何时rollback。
定义TransactionTemplate
public class SimpleService implements Service {
private final TransactionTemplate transactionTemplate;
public SimpleService(PlatformTransactionManager transactionManager){
this.transactionTemplate = new TransactionTemplate(transactionManager);
this.transactionTemplate.setIsolationLevel(TransactionTemplate.ISOLATION_READ_UNCOMMITTED);
this.transactionTemplate.setTimeout(30);
}
}
使用TransactionTemplate
public Object someMethod(){
return transactionTemplate.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
updateOpertion();
return resultOfUpdateOperation2();
}
});
}
只做更新,不需要返回值
public void someMethodWithoutResult(){
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
updateOpertion1();
updateOpertion2();
}
});
}
如果需要做异常处理
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try{
updateOpertion1();
updateOpertion2();
} catch (SomeBusinessExetion ex){
status.setRollbackOnly();
}
}
PlatformTransactionManager的实现
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("SomeTxName");
def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
doSomeTransactionLogic();
}catch (MyExpiton ex){
txManager.rollback(status);
throw ex;
}