您的位置:首页 > 编程语言 > Java开发

Spring事务管理-使用基础

2017-09-13 11:50 274 查看

Spring提供的事物管理有两种:

编程式事物(使用TransactionTemplate,粒度控制在代码块,手动提交)

声明式事务(XML、注解, 粒度只能控制在public方法)

事务管理是基于数据源的,也就是说mybatis引用的数据源必须和DataSourceTransactionManager引用的数据源一致。这样事务管理才能生效。

Spring 事务特性。

Spring所有的事务管理策略都继承于
org.springframework.transaction.PlatformTransactionManager
接口

public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

void commit(TransactionStatus status) throws TransactionException;

void rollback(TransactionStatus status) throws TransactionException;
}


一般我们使用的都是DataSourceTransactionManager,也就是基于数据源的事务管理。我们先看看DataSourceTransactionManager的类继承关系:



我们从上面图中看到两个很重要的接口:PlatformTransactionManager 和 InitializingBean 。实现了PlatformTransactionManager说明这个类主要功能是进行事务管理;实现了InitializingBean接口,从bean的生命周期来看,我们知道InitializingBean#afterPropertiesSet() 是在单例的bean的第二阶段,populate属性之后调用的,我们看看DataSourceTransactionManager里面的实现,从下面源码可知,DataSourceTransactionManager进行事务管理的前提是DataSource已经成功注入。

@Override
public void afterPropertiesSet() {
if (getDataSource() == null) {
throw new IllegalArgumentException("Property 'dataSource' is required");
}
}


前面介绍了DataSourceTransactionManager与数据源的关系,那么Spring对事务是怎么支持的呢?

TransactionDefinition接口里面定义了事务的隔离级别和事务的传播行为:

Spring中事务隔离级别

::隔离级别::是指若干个并发事务之间的隔离程度,以MySQL为例,我们知道在MySQL中定义了四种事务的隔离级别:

1. Read Uncommitted(未提交读)

2. Read Committed(提交读)

3. Repeatable Read(可重复读)(MySQL默认)

4. Serializable(可串行化)

在Spring的事务管理中一样,TransactionDefinition也定义了5种隔离级别

//底层数据库默认的隔离级别,这个与具体数据库有关系
int ISOLATION_DEFAULT = -1;
// 未提交读
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
// 提交读:只能读取别人commit了的数据
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
// 可重复读:存在幻读,不过MySQL通过MVCC解决这个问题
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
// 串行化
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;


Spring的事务传播行为

这一点是比较难理解的一点,所谓::事务传播行为::是指:如果在开始当前事务之前,一个事务上下文已经存在了,此时有若干选项可以指定一个事务性方法的执行行为。

在TransactionDefinition中同样定义了如下几种事务传播行为:

// 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
int PROPAGATION_REQUIRED = 0;
// 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
int PROPAGATION_SUPPORTS = 1;
// 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
int PROPAGATION_MANDATORY = 2;
// 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
int PROPAGATION_REQUIRES_NEW = 3;
// 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
int PROPAGATION_NOT_SUPPORTED = 4;
// 以非事务方式运行,如果当前存在事务,则抛出异常。
int PROPAGATION_NEVER = 5;
// 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;
// 如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
int PROPAGATION_NESTED = 6;


事务超时时间

所谓::事务超时::就是指:一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。

默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。

事务只读属性

只读事务用于客户代码只能读但不修改数据的情形,只读事务用于特定情景下的优化。

Spring事务回滚规则

其实也就是在事务内部如果抛出了异常,Spring的事务回滚规则是怎么样的。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。

默认配置:spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。

我们可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。

::@Transactional 注解::

::属性::

* transactionManager : 指定使用的事务管理器,这也是注解的默认值

* propagation:事务传播行为

* isolation:事务隔离级别

* readOnly:是否是只读

* timeout:超时时间

* rollbackFor:导致事务回滚的异常类数组

* rollbackForClassName:导致事务回滚的异常类名字数组

* noRollbackFor:不会导致事务回滚的异常类数组

* noRollbackForClassName:不会导致事务回滚的异常类名字数组

::注解作用域::

作用于类以及类方法上。但是只能作用域public方法,因为是基于AOP实现的。

本文涉及的核心类

PlatformTransactionManager 接口以及其子类

DataSourceTransactionManager 类

TransactionDefinition

从上文我们可以知道,其实Spring的事务管理其实就是基于DataSource的事务管理,也就是基于数据库的事务原理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring 事务