Spring Transaction 事务控制

数据库事务的概念:事务能够看作是一系列操做组成的工做单元。这个工做单元是一个完整主体。工做单元中的一系列操做要么都执行成功,要么都执行失败。web

事务的四个特性(ACID):数据库

1.原子性(Atomicity):事务是不可分割的工做单元。要么都执行成功,要么都不成功编程

2.一致性(Consistency):事务的执行不会破坏数据库的完整性。并发

3.隔离性(Isolation):并发的事务之间相互之间不影响,经过事务隔离级别来指定隔离性ui

4.持久性(Durability):事务一旦执行完成以后,对数据库的修改是永久性的。不会被外界因素改变。spa

在实际的开发过程当中,常常会后并发访问数据库的状况。即多个事务同时修改数据库信息。常见的问题包括:.net

丢失更新:当某一个事务修改了数据库的某条记录,在该事务提交前,另外一个事务也对该条记录作了修改。前一个事务的修改被后面的事务修改给覆盖了。代理

         致使第一个事务修改的数据丢失,这是因为没有对修改记录加锁形成的。接口

脏读:一个事务读到了另外一个事务还未提交的数据。事务

不可重复读:同一个事务两次查询同一条记录返回的结果不同,因为两次查询中另外一个事务对该记录修改形成的。

幻读:同一事务两次查询结果不一样,因为两次查询中另以事务又插入了新的数据,两次查询出了两批记录,好像出现了幻觉同样。

上述问题的发生都是因为并发事务之间的隔离没有作好而引发的。解决这些问题就是设置合理的事务隔离级别。

事务的隔离级别包括:未提交读(read_uncommitted)、提交读(read_commit)、可重复读(repeatable_read)、序列化(serialable).

四个隔离级别的隔离性是递增的。隔离级别越高,数据库的并发能力就越差,因此在实际开发过程当中须要在数据库并发能力和知足实际业务要求之间作权衡。

未提交读:最低的隔离级别,可能致使丢失更新、脏读、不可重复读、幻读。

提交读:一个事务只能读到其余事务提交以后的数据,这个是大多数数据库默认的隔离级别。能够避免丢失更新和脏读。仍有可能形成不可重复读和幻读。

可重复读:能够避免丢失更新、脏读、不可重复读。可能形成幻读。

序列化:最高的隔离级别,事务之间没有并发能力,全部事务都是串行化运行的。能够避免丢失更新、脏读、不可重复读、幻读。

Spring 提供了统一的事务管理。根据事务的配置方式不一样能够分为:编程式事务和声明式事务两种。

建议使用声明式事务,其中声明式事务又分为两种:一种是使用注解@Transactional声明;另外一种是使用切面的方式统一进行拦截。

注解方式相对灵活,切面方式比较依赖前期的约定和配置。因为前期的项目约定并不完整,咱们项目中采用了注解的方式进行事务的控制。

Spring使用@Transaction来指定事务属性,能够在接口、类或方法上指定,若是类和方法上都指定了
@Transaction ,则方法上的事务属性被优先使用,具体属性以下:
• value:指定事务管理器名字,默认使用<tx:annotation-driven/>指定的事务管理器,用于支持多事务管理器环境;
• propagation:指定事务传播行为,默认为Required,使用Propagation.REQUIRED指定;
• isolation:指定事务隔离级别,默认为“DEFAULT”,使用Isolation.DEFAULT指定;
• readOnly:指定事务是否只读,默认false表示事务非只读;
• timeout:指定事务超时时间,以秒为单位,默认-1表示事务超时将依赖于底层事务系统;
• rollbackFor:指定一组异常类,遇到该类异常将回滚事务;
• rollbackForClassname:指定一组异常类名字,其含义与<tx:method>中的rollback-for属性语义彻底同样;
• noRollbackFor:指定一组异常类,即便遇到该类异常也将提交事务,即不回滚事务;
• noRollbackForClassname:指定一组异常类名字,其含义与<tx:method>中的no-rollback-for属性语义彻底同样;

下面介绍一下propagation和isolation属性对应的值的含义:

1.propagation对应的值是一个枚举包含如下几个值:

     REQUIRED:这是propagation的默认值,若是当前存在事务则加入事务,若是不存在事务则建立一个事务。

SUPPORTS:若是当前存在事务则加入事务,若是不存在就已无事务的方式运行。
MANDATORY:强制必须当前有事务存在,若是不存在事务则抛出异常。
REQUIRES_NEW:无论当前有没有事务,都建立一个新的事务。
NOT_SUPPORTED:若是当前存在事务,那么中止使用事务。
NEVER:强制不使用事务,若是当前存在事务则抛出异常
NESTED:若是一个活动的事务存在,则运行在一个嵌套的事务中,若是没有活动的事务,则按照REQUIRED属性执行,它使用一个单独的事务。
        这个事务拥有多个回滚的保存点,内部事务的回滚不会对外部事务形成影响,它只对DataSource TransactionManager事务管理器起效。

2.isolation对应的值也是一个枚举包含如下几个值(对应前面讲到的开发常见问题解决方案):

     DEFAULT:默认的隔离级别

READ_UNCOMMITTED:未提交读

READ_COMMITTED:提交读

REPEATABLE_READ:可重复读

SERIALIZABLE:序列化

Spring官方文档上的描述是这样的:

You can place the @Transactional annotation before an interface definition, a method on an Interface a class definition, or a public method on a class

可是建议只在实现类和实现类的方法上进行注解的使用。由于若是使用CGLIB的方式代理机制接口上的@Transactional是不会被实现类集成下来的,可能会形成配置事务没法使用的问题。先写到这若有疑问欢迎前来探讨!

相关文章
相关标签/搜索