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

Spring 的事务处理浅谈

2016-02-05 17:16 399 查看
事务的概念:

这里与spring无关,事务的最基础概念源于对数据库的操作时由并发带来的问题;

简单的栗子参照提款机取款或者银行转账;

事务的特性:

1) 原子性(atomicity):事务是数据库的逻辑工作单位,而且是必须是原子工作单位,对于其数据修改,要么全部执行,要么全部不执行。

2) 一致性(consistency):事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。

3) 隔离性(isolation):一个事务的执行不能被其他事务所影响。

4) 持久性(durability):一个事务一旦提交,事物的操作便永久性的保存在DB中。即使此时再执行回滚操作也不能撤消所做的更改。

在并发处理中事务带来的问题:

1)第一类丢失更新:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。

2)脏读:一个事务读到另一个事务未提交的更新数据。

3)幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。

4)不可重复读:一个事务两次读同一行数据,可是这两次读到的数据不一样。

5)第二类丢失更新:这是不可重复读中的特例,一个事务覆盖另一个事务已提交的更新数据。

事务的隔离级别:

DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .

READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )

READ_COMMITTED 会出现不可重复读、幻读问题(锁定正在读取的行)

REPEATABLE_READ 会出幻读(锁定所读取的所有行)

SERIALIZABLE 保证所有的情况不会发生(锁表)

事务的隔离级别定义了事务在执行过程中所使用的隔离级别和安全以及性能等因,一般会使用默认的级别,但也可以随着使用需求选择适合的级别;

而事务的传播行为则在定义了隔离级别的基础上定义事务的执行方式;

在org.springframework.transaction.TransactionDefinition.class的源码中有对于Spring事务传播行为的注释,其中提到了这样的东西:
/**
* Support a current transaction; create a new one if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p>This is typically the default setting of a transaction definition,
* and typically defines a transaction synchronization scope.
*/
int PROPAGATION_REQUIRED = 0;


EJB的概念:

这个不是重点,如果没有相关了解的同学可以简单理解为这是一个先于Spring存在的架构规范,属于javaEE的一部分;问题是这里提到了Spring对于事务传播行为的定义参考了EJB,也可以说几乎相同;

事务的传播行为:

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

Spring中对事务的使用方式:

Spring中提供了声明式事务和编程式事务弓开发者使用,就入门和使用阶段,个人觉得这两种方式没有太大的区别;在网上找了一圈,有很多大牛从源码角度对这两种方式进行了比较详细的比较和分析,有兴趣可以看看《Spring编程式事务与声明式事务源码分析》

1) 编程式事务:
public void yourMethod(Parameter parameter){

TransactionStatus status = null;

try{

// balabala...

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
status = txManager.getTransaction( def );

// balabala...

yourMethodB();
yourMethodC();

txManager.commit(status);

}catch(Exception e){

if(status != null && !status.isCompleted()){
txManager.rollback(status);
}
}
}


在以上代码中针对事务的控制由txManager将事务开启,中间的部分可以填写业务逻辑代码,同时methodB和methodC中如果依然有数据库操作,会和外层方法(yourMethod) 保持在一个事务中;当yourMethod内部抛出异常,整个事务即会回滚;同样的,内部方法yourMethodB和yourMethodC中抛出的异常,只要没有被catch住,即可连同外层的方法维持的事务一并进行回滚;

2)声明式事务

@Transactional(propagation = Propagation.REQUIRED)
public void yourMethod(Parameter parameter){

// balabala...

yourMethodB();
yourMethodC();

// balabala...

}
注解Transactional可以起到和上面编程式事务同样的功能,其中propagation配置的是事务的传播行为;

回滚机制同理,内层方法如果出现异常,不对其进行捕获或者抛出RuntimeException时,外层方法会对整个方法维持的事务进行回滚;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: