Spring中的事务管理是通过AOP实现自身功能增强的典型模块,在这个模块中 Spring把在企业应用中事务处理的主要过程抽象出来 并且通过简洁的aop的切面增强实现了声明事务处理的功能 简单的说 我们只需要在IOC容器中对事务属性进行配置即可完成 同时这些事务处理的基本过程和具体的事务处理器实现是无关的 也就是说 应用可以选择不同的具体的事务处理机制 如JTA JDBC HIBERNATE 因为采取了声明式事务处理(结合aspectJ) 所以这些事务处理机制被纳入spring事务处理的统一框架中 并完全与具体业务代码解耦。
还是通过代码来阐述吧:
applicationContext.xml
<!--事务管理DataSourceTransactionManager -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
//DataSourceTransactionManager类就是JDBC事务管理器
//这个是可以换成其他事务管理器的 比如 支持分布式事务管理的JTA 再或者hibernate事务管理器等
//如果仅仅看这个事务管理器的话 是完全与业务代码解耦的 具体在什么sql上植入事务 是由下面的配合aspectJ的aop来植入的
<property name="dataSource" ref="defaultDataSource" />
</bean>
<!-- 针对注解声明式的事物 -->
<tx:annotation-driven transaction-manager="txManager" />
//<tx:annotation-driven />这个标签仅仅是声明了个针对注解的事务
//真正完成事务管理的是transaction-manager="txManager" 是里面引用的事务管理器 这个才是核心
<aop:config>
<!-- <aop:pointcut id="baseServiceMethods" expression="execution(* com.gwssi.*.service..*.*(..))"
/> -->
<aop:pointcut id="baseServiceMethods"
expression="target(com.gwssi.optimus.core.service.BaseService)" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="baseServiceMethods" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="select*" read-only="true" propagation="SUPPORTS"
rollback-for="Exception" />
<tx:method name="find*" read-only="true" propagation="SUPPORTS"
rollback-for="Exception" />
<tx:method name="do*" propagation="REQUIRED" isolation="READ_COMMITTED"
rollback-for="Exception" />
<tx:method name="insert*" propagation="REQUIRED" isolation="READ_COMMITTED"
rollback-for="Exception" />
<tx:method name="update*" propagation="REQUIRED" isolation="READ_COMMITTED"
rollback-for="Exception" />
<tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"
rollback-for="Exception" />
<tx:method name="delete*" propagation="REQUIRED" isolation="READ_COMMITTED"
rollback-for="Exception" />
</tx:attributes>
</tx:advice>
JDBC事务的优缺点:
JDBC为使用Java进行数据库的事务操作提供了最基本的支持。通过JDBC事务,我们可以将多个SQL语句放到同一个事务中,保证其ACID特性。JDBC事务的主要优点就是API比较简单,可以实现最基本的事务操作,性能也相对较好。
但是,JDBC事务有一个局限:一个 JDBC 事务不能跨越多个数据库
所以,如果涉及到多数据库的操作或者分布式场景,JDBC事务就无能为力了。
引用网上对JTA的解释
通常,JDBC事务就可以解决数据的一致性等问题,鉴于他用法相对简单,所以很多人关于Java中的事务只知道有JDBC事务,或者有人知道框架中的事务(比如Hibernate、Spring)等。但是,由于JDBC无法实现分布式事务,而如今的分布式场景越来越多,所以,JTA事务就应运而生。
如果,你在工作中没有遇到JDBC事务无法解决的场景,那么只能说你做的项目还都太小。拿电商网站来说,我们一般把一个电商网站横向拆分成商品模块、订单模块、购物车模块、消息模块、支付模块等。然后我们把不同的模块部署到不同的机器上,各个模块之间通过远程服务调用(RPC)等方式进行通信。以一个分布式的系统对外提供服务。
一个支付流程就要和多个模块进行交互,每个模块都部署在不同的机器中,并且每个模块操作的数据库都不一致,这时候就无法使用JDBC来管理事务。
JTA里面提供了 java.transaction.UserTransaction
,里面定义了下面几个方法
JTA的优点很明显,就是提供了分布式事务的解决方案,严格的ACID。但是,标准的JTA方式的事务管理在日常开发中并不常用,因为他有很多缺点:
- 实现复杂
- 通常情况下,JTA UserTransaction需要从JNDI获取。这意味着,如果我们使用JTA,就需要同时使用JTA和JNDI。
- JTA本身就是个笨重的API
- 通常JTA只能在应用服务器环境下使用,因此使用JTA会限制代码的复用性。
begin
:开启一个事务
commit
:提交当前事务
rollback
:回滚当前事务
setRollbackOnly
:把当前事务标记为回滚
setTransactionTimeout
:设置事务的事件,超过这个事件,就抛出异常,回滚事务
这里,值得注意的是,不是使用了UserTransaction
就能把普通的JDBC操作直接转成JTA操作,JTA对DataSource、Connection和Resource 都是有要求的,只有符合XA规范,并且实现了XA规范的相关接口的类才能参与到JTA事务中来,关于XA规范,请看我的另外一篇文章中有相关介绍。这里,提一句,目前主流的数据库都支持XA规范。
XA规范不知道的童鞋请看我的另一篇文章 《XA规范简洁》
下一篇文章我将会介绍一种阿里巴巴的分布式事务管理机制 dubbo分布式事务管理 以及用法 请关注。。。