java事务
1.概念
2.分类
3.声明式事务实现
4.执行流程
5.@Transactional注解
6.注意事项
7.事务传播机制
8.事务隔离
1.概念
事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性;
事务必须服从ACID原则。ACID指的是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。
原子性:操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态。
一致性:事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。
隔离性:在该事务执行的过程中,无论发生的任何数据的改变都应该只存在于该事务之中,对外界不存在任何影响。只有在事务确定正确提交之后,才会显示该事务对数据的改变。其他事务才能获取到这些改变后的数据。
持久性:当事务正确完成后,它对于数据的改变是永久性的。
2.分类
编程式事务管理:
将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式管理事务中,必须在每个事务操作中包含额外的事务管理代码。
声明式事务管理:
大多数情况下比编程式事务管理更好用,它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理,Spring声明式事务管理建立在AOP基础之上,是一个典型的横切关注点,通过环绕增强来实现,其原理是对方法前后进行拦截,然后在目标方法开始之前创建或加入一个事务,在执行完毕之后根据执行情况提交或回滚事务。
我们着重介绍声明式事务管理。
3.声明式事务实现
1、添加spring-aspects-4.3.10.RELEASE.jar包
2、在Spring配置文件中添加如下配置:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
3.在Service层public方法上添加事务注解——@Transactional
4.执行流程
容器在刚开始扫描时,会为带有@Transactional注解的public方法创建代理对象,进行事务管理。
当执行到这个方法的时候,如果抛出了运行时异常,则事务回滚,如果没有抛出异常或者抛出的是检查时异常,则事务提交。
5.@Transactional注解
1.rollbackFor 属性:指定对哪些异常回滚事务。
即使是检查时异常,如果我们需要让这个事务回滚,可以为注解该属性设置值,值为异常类,这样在抛出检查时异常时同样可以回滚。
@Transactional(rollbackFor=Exception.class)
2.noRollbackFor 属性:指定对哪些异常不回滚事务。
与上面类似,如果需要在抛出运行时异常时也不让事务回滚,为注解该属性设置值,值也为异常类,这样在抛出运行时异常时也不会回滚,成功提交。
@Transactional(noRollbackFor=RuntimeException.class)
3.readOnly 属性:指定是否对数据库进行只读操作。
该属性的值为boolean类型,默认为false,即可对数据库进行读写操作,如果指定属性为true,则将只能对数据库进行读操作,否则将会抛出异常保证了一定的安全性。
@Transactional(readOnly=true)
4.timeout 属性:方法执行的最大时间。
该属性的值单位为秒,即如果该方法执行时间超过此设置的值,事务将提交失败,自动回滚。
@Transactional(timeout=2)
6.注意事项
1.不能在protected、默认或者private的方法上使用@Transactional注解,否则无效。
2.方法中的如果抛出的异常被 try-catch 处理,那么相当于未检测到抛出了异常,仍会提交事务。
7.事务传播机制
propagation 也是@Transactional注解中的一个属性,但是它代表的是一种传播机制,因此单独拿出来谈。
有两种常用的传播方式:REQUIRED 和 REQUIRES_NEW
通过简单的例子来了解这两种行为:
方法A调用方法B,两个方法的事务传播属性均为x,当x分别为这两种值时,会有不同的情况出现。
REQUIRED:(默认值)如果有事务在运行,当前的方法就在这个事务内运行,否则以非事务的方式运行;
由于两个方法处于一个事务 ,只要有一个方法中抛出运行时异常,两个方法都会回滚。
REQUIRES_NEW:当前方法必须启动新事务,并在它自己的事务内运行,如果有事务在运行,则把当前事务挂起,直到新的事务提交或者回滚才恢复执行。
由于在不同的事务内运行,就互不相关,哪一个方法抛出运行时异常就回滚哪个方法,而另一个方法并不会收到影响。
8.事务隔离
隔离级别共五个级别,它们代表着不同事务对于相同数据的读写操作时处理的机制。
1. Read uncommitted (读未提交)
当事务A在事务中处理数据1时,如果事务B访问数据1,不管事务A是否提交,事务A对数据1修改成什么样子,事务B访问数据1的值就是什么样子。
2.Read committed (读提交)
当事务A在事务中处理数据1时,会将数据1所在行锁住。如果事务B访问数据1,如果事务A未提交,事务B访问到的就是数据1在被事务A处理之前的值,如果事务A已提交,事务B访问到的就是数据1在被事务A处理后的值。
3.Repeatable read (重复读)
当事务A在事务中更新数据1时,会将数据1所在表锁住。如果事务B在数据1所在表添加信息数据2时,如果事务A未提交,事务B将无法添加,因此此张表已被锁住,如果事务A已提交,事务B即可添加。
4.Serializable (序列化 )
当事务A在事务中访问数据1时,不管是否更新数据1,事务B均无法访问数据1所在表上的任何数据,很显著的缺点就是并发行极低。