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

spring事务管理

2016-04-20 16:37 351 查看
转自:http://www.jb51.net/article/57589.htm

事务就是一系列的动作,它们被当作一个单独的工作单元。这些动作要么全部完成,要么全部不起作用。

事务的四个关键属性(ACID)

① 原子性(atomicity):事务是一个原子操作,有一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用

② 一致性(consistency):一旦所有事务动作完成,事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中

③ 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏

④ 持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中

Spring既支持编程式事务管理,也支持声明式的事务管理

编程式事务管理:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码

声明式事务管理:大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring通过Spring AOP框架支持声明式事务管理。

Spring事务的传播属性:

传播行为含义
PROPAGATION_MANDATORY表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
PROPAGATION_NESTED表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务
PROPAGATION_NEVER表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
PROPAGATION_NOT_SUPPORTED表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_REQUIRED表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
PROPAGATION_REQUIRED_NEW表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_SUPPORTS表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
其中PROPAGATION_REQUIRED为默认的传播属性

并发事务所导致的问题

在同一个应用程序或者不同应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题。

并发事务所导致的问题可以分为以下三类:

① 脏读:脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。

② 不可重复读:不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间更新了数据

③ 幻读:幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录

/**

* 1.添加事务注解

* 使用propagation 指定事务的传播行为,即当前的事务方法被另外一个事务方法调用时如何使用事务。

* 默认取值为REQUIRED,即使用调用方法的事务

* 2.使用isolation 指定事务的隔离级别,最常用的取值为READ_COMMITTED

* 3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚,也可以通过对应的属性进行设置。通常情况下,默认值即可。

* 4.使用readOnly 指定事务是否为只读。 表示这个事务只读取数据但不更新数据,这样可以帮助数据库引擎优化事务。若真的是一个只读取数据库值得方法,应设置readOnly=true

* 5.使用timeOut 指定强制回滚之前事务可以占用的时间。

*/

@Transactional(propagation=Propagation.REQUIRES_NEW,

isolation=Isolation.READ_COMMITTED,

noRollbackFor={UserAccountException.class},

readOnly=true, timeout=3)

转自:http://www.educity.cn/wenda/371314.html

事务最重要的两个特性,是事务的传播级别和数据隔离级别。传播级别定义的是事务的控制范围,事务隔离级别定义的是事务在数据库读写方面的控制范围。

数据隔离级别分为不同的四种:

1、Serializable :最严格的级别,事务串行执行,资源消耗最大;

2、REPEATABLE READ :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。

3、READ COMMITTED :大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。

4、Read Uncommitted :保证了读取过程中不会读取到非法数据。

上面的解释其实每个定义都有一些拗口,其中涉及到几个术语:脏读、不可重复读、幻读。

这里解释一下:

脏读 :所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。

不可重复读 :不可重复读字面含义已经很明了了,比如事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。

幻读 :小的时候数手指,第一次数十10个,第二次数是11个,怎么回事?产生幻觉了?

幻读也是这样子,事务A首先根据条件索引得到10条数据,然后事务B改变了数据库一条数据,导致也符合事务A当时的搜索条件,这样事务A再次搜索发现有11条数据了,就产生了幻读。

一个对照关系表:

             Dirty reads     non-repeatable reads      phantom reads

Serializable           不会          不会              不会

REPEATABLE READ      不会          不会              会

READ COMMITTED      不会          会               会

Read Uncommitted      会           会               会

所以最安全的,是Serializable,但是伴随而来也是高昂的性能开销。

另外,事务常用的两个属性:readonly和timeout

一个是设置事务为只读以提升性能。

另一个是设置事务的超时时间,一般用于防止大事务的发生。还是那句话,事务要尽可能的小!

============================================================
以下为转载 clarck_913 在http://bbs.csdn.net/topics/290021423/下的回复。

AOP是面向切面的编程

在Spring里,只有面向方法的切面。

比如你有一个方法A和方法B,你希望在A执行前执行方法B,但不能把B的代码贴到A中

因为和A类似的方法有很多,如果你全都贴过去的话,工作量大并且是重复的工作

这个时候你就定义了A为切面,B为处理程序。Spring 会在你调用A方法时自动执行B方法

实际过程是Spring 为含有A方法的类生成了一个代理类,该类也有一个叫A的方法但其实现却是 B+A的实现

你调用A的时候,调用的对象是代理对象,但是你并不知道。

事务的编程正是上述情况的典型

事务处理代码是B(提交,回滚),事务执行代码是A(增删改查)

在Spring 中已经内置了事务处理代码,也就是B,所以我们写A方法,然后配置事务就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: