Spring事务管理
事务管理的核心接口
1.Platform TransactionManager(平台事务管理器)
PlatformTransactionManager接口是Spring提供的平台事务管理器,主要用于管理事务。该接口中提供了三个事务操作的方法,具体如下:
-
TransactionStatus getTransaction(TransactionDefinition definition);
用于获取事务以及状态信息 -
void commit(TransactionStatus status);
用于提交事务 -
void rollback(TransactionStatus status);
用于回滚事务PlatformTransactionManager接口只是代表事务管理的接口,并不知道底层是如何管理事务的,具体如何管理事务则由它的实现类来完成。
该接口常见的几个实现类:
-
org.springframework.jdbc.datasource.DataSourceTransactionManager(用于配置jdbc数据源的事务管理器)
-
org.springframework.orm.hibernate4.HibernateTransactionManager(用于配置Hibernate的事务管理器)
-
org.springframework.transaction.jta.JtaTransactionManager(用于配置全局事务管理器)
******小提示:当底层采用不同的持久层技术时,系统只需使用不同的PlatformTransactionManager实现类即可。
-
2.TransactionDefinition
TransactionDefinition接口是事务定义(描述)的对象,该对象中定义了事务基本属性,并提供了获取事务基本属性的方法,具体如下:
String getName( ); 获取事务对象名称
int getIsolationLevel( ); 获取事务的隔离级别
int getPropagationBehavior( ); 获取事务的传播行为
int getTimeout( );获取事务的超时时间
boolean isReadOnly( ); 获取事务是否只读
3.TransactionStatus
TransactionStatus接口是事务的状态,它描述了某一时间点上事务的状态信息。该接口中包含6个方法,具体如下:
void flush(); 刷新事务
boolean hasSavepoint(); 获取是否存在保存点
boolean isCompleted(); 获取事务是否完成
boolean isNewTransaction(); 获取是否为新事务
boolean isRollbackOnly(); 获取事务是否回滚
void setRollbackOnly(); 设置事务回滚
事务的基本事务属性
传播行为(propagetionBehavior):当事务方法被另一个事务方法调用时,必须指定事务应该如何传播
隔离级别(isolationLevel):一个事务可能受其他并发事务的影响。多个事务并发运行,经常会出现操作相同的数据来完成各自的任务,可能出现脏读,幻读,不可重复读的问题。隔离级别有四种
是否只读(readOnly):如果一个方法内都是数据库的select操作,那么可以设置为只读,只读事务内不能有insert,update,delete的操作
事务超时(timeout):设置事务超时时间可以及时释放资源
事务管理的方式
1.编程式事务管理:通过编写代码实现的事务管理
包括定义事务的开始、正常执行后的事务提交、异常时的事务回滚
步骤1:
在applicationContext.xml中添加事务管理器组件
<!--定义事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
步骤2:
在业务逻辑类service中使用事务管理器
通过依赖注入使用事务管理器
@Autowired
private PlatformTransactionManager txManager;
步骤3:
在方法中编程实现事务管理
//定义事务规则(隔离级别、传播行为)
DefaultTransactionDefinition definition=new DefaultTransactionDefinition();
//开启事务管理,并返回事务状态
TransactionStatus status = txManager.getTransaction(definition);
try {
//转账业务逻辑(省略)
txManager.commit(status); //提交事务
} catch (Exception e) {
txManager.rollback(status); //如果出现异常回滚事务
}
缺点:和业务逻辑代码产生耦合,产生了代码冗余,不方便代码的维护和扩展
2.声明式事务管理:通过XML配置或者注解的方式实现的事务管理
声明式事务管理的原理是什么?
通过AOP技术实现的事务管理,将事务作为一个切面代码单独编写,然后通过AOP技术将事务管理的切面植入到业务目标类中
基于XML方式的声明式事务
在配置文件中通过<tx:advice>元素配置事务规则来实现,然后通过aop:config编写的AOP配置,让Spring自动对目标生成代理
步骤1:
添加事务管理器组件
<!--定义事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
同编程式类似
步骤2:
使用tx:advice标签配置事务规则
<!-- 配置事务规则 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 定义哪些方法需要进行事务处理,*表示任意字符 -->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="moneyTransfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
- SUPPORTS(支持):
- 如果当前存在事务,则方法在该事务中运行。
- 如果当前没有事务,则方法在非事务状态下运行。
- 支持当前事务,但不会强制要求存在事务。
2.REQUIRED(必须):
-
如果当前存在事务,则方法在该事务中运行。
-
如果当前没有事务,则创建一个新的事务,并在该事务中运行方法。
-
如果方法被调用的上下文中已经存在一个事务,那么方法将在该事务中运行,否则将创建一个新的事务。
步骤3:使用<aop:config>配置事务切面,并应用事务规则
<!-- 定义切面 -->
<aop:config>
<!-- 定义切点范围 -->
<aop:pointcut expression="execution(* service.*.*(..))" id="pointcut"/>
<!-- 应用事务规则 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
基于注解方式的声明式事务
1、配置事务管理器(所有方式都包含了这个步骤)
<!--定义事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
2、在Spring容器中注册事务注解驱动:
<tx:annotation-driven transaction-manager=“txManager"/>
3、在需要事务管理的类或方法上使用@Transactional注解
如果将注解添加在Bean类上,则表示事务的设置对整个Bean类的所有方法都起作用;
如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该方法有效。
ng容器中注册事务注解驱动:
<tx:annotation-driven transaction-manager=“txManager"/>
3、在需要事务管理的类或方法上使用@Transactional注解
如果将注解添加在Bean类上,则表示事务的设置对整个Bean类的所有方法都起作用;
如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该方法有效。
声明式默认只对RuntimeException及其子类异常回滚,如果是自定义异常,那么rollback-for可以回滚