Spring 框架中,涉及到事务管理的 API 大约有100个左右,其中最重要的有三个:TransactionDefinition、PlatformTransactionManager、TransactionStatus。

1、org.springframework.transaction.TransactionDefinition,它用于定义一个事务。它包含了事务的静态属性,比如:事务传播行为、隔离级别、超时时间等等。

wKioL1iYRi2jSv47AAA-pQfu-Kc846.png

Spring 为我们提供了一个默认的实现类:DefaultTransactionDefinition,该类适用于大多数情况。如果该类不能满足需求,可以通过实现 TransactionDefinition 接口来实现自己的事务定义。

wKiom1iYRi_DlNurAADCweOsT9c214.png

2、org.springframework.transaction.PlatformTransactionManager,用于执行具体的事务操作,方法列表如下:全部抛出TransactionException异常

wKiom1iYRizAPu_iAAAY25Tdllg370.png

PlatformTransactionManager 的主要实现类大致如下:

wKioL1iYRjGiHEl-AACPwH4KMAk869.png


根据底层所使用的不同的持久化 API 或框架,使用如下:

 DataSourceTransactionManager:适用于使用JDBC和iBatis进行数据持久化操作的情况。

 HibernateTransactionManager:适用于使用Hibernate进行数据持久化操作的情况。

 JpaTransactionManager:适用于使用JPA进行数据持久化操作的情况。

 另外还有JtaTransactionManager 、JdoTransactionManager、JmsTransactionManager等等。

如果我们使用JTA进行事务管理,我们可以通过 JNDI 和 Spring 的 JtaTransactionManager 来获取一个容器管理的 DataSource。JtaTransactionManager 不需要知道 DataSource 和其他特定的资源,因为它将使用容器提供的全局事务管理。而对于其他事务管理器,比如DataSourceTransactionManager,在定义时需要提供底层的数据源作为其属性,也就是 DataSource。与 HibernateTransactionManager 对应的是 SessionFactory,与 JpaTransactionManager 对应的是 EntityManagerFactory 等等。

下面分析DataSourceTransactionManager,指明dataSourcce:javax.sql.DataSource。

wKiom1iYRiyhp2ZxAABWuxSXXks378.png

注入dataSourcce

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

         <property name="dataSource" ref="dataSource" />

</bean>  

3、TransactionStatus

PlatformTransactionManager.getTransaction(…) 方法返回一个 TransactionStatus 对象。返回的TransactionStatus 对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事务)。TransactionStatus 接口提供了一个简单的控制事务执行和查询事务状态的方法。


TransactionStatus 接口中定义的主要方法

public  interface TransactionStatus{

   boolean isNewTransaction();

   void setRollbackOnly();

   boolean isRollbackOnly();

}

4、总的示例代码:

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(jdbcTemplate.getDataSource());

TransactionStatus status = transactionManager.getTransaction(def);

try {

    //一些执行sql的代码

    transactionManager.commit(status);

} catch (Exception ex) {

    transactionManager.rollback(status);

}

要保证要使用同一个DataSourceTransactionManager。

5、其他

对于编程式事务管理,spring推荐使用TransactionTemplate。

声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。基于注解的方式更简单易用,更清爽。

spring会将底层连接的自动提交特性设置为false。

当一个连接关闭时,如果有未提交的事务应该如何处理?JDBC规范没有提及,C3P0默认的策略是回滚任何未提交的事务。

MyBatis自动参与到spring事务管理中,无需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源与DataSourceTransactionManager引用的

数据源一致即可,否则事务管理会不起作用。

另外需要引入依赖包aopalliance.jar,否则spring初始化时会报异常java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。