一、什么是事务
1、概念:把一组业务当成一个业务来做,要么都成功,要么都不成功,是保证业务操作完整行的一种数据库机制。
2、种类:在事务控制方面主要有两个分类。
1、编程式事务:在代码中直接加入处理事务的逻辑,可能需要在代码中调试一些事务管理的相关方法。
2、声明式事务:在方法的外部添加注解或者直接在配置文件中定义,将事务管理代码从业务中分离处理,以声明的方式实现食物管理。Spring 的AOP就可以实现该功能:事务管理代码的固定模式作为一种横切关注点,通过AOP方法模块化,进而实现声明式事务。
3、声明式事务的特性:ACID
A原子性:一个事务中的所有操作,要么都成功,要么都失败,不会结束在中间的某个环节。事务执行过程中发生错误,会被回滚到食物开始前的状态,就像这个事务没有执行过一样。即:事务不可再分,不可约简。
C一致性:在事务开始之前和结束之后,数据库的完整性没有被破坏,保证数据的一致性。
I 隔离性:在并发的情况下,事务之间要相互隔离,防止多个事务兵法之行时由于交叉执行而导致的数据不一致情况,事务的隔离级别有四个,下面会详细介绍。
D持久性:数据处理结束后,对数据的修改就是永久性的,即便系统故障也不会丢失。
二、怎么实现声明式事务
1、声明式事务配置介绍
1)Spring从不同的事务管理API中抽出了一整套食物管理机制,让食物管理代码从特定的食物技术中独立出来。开发人员通过配置的方式进行食物管理,而不必了解底层是如何实现的。
Spring的核心食物管理抽象是PlatformTransactionManager。它为事务管理封装了一组独立于技术的方法。无论使用Spring的哪种事务(编程式、声明式),事务管理器都是必须的。
事务管理器可以以普通的bean形式声明在Spring IOC容器中。
2)Spring提供的事务管理器
配置文件中配置
<!‐‐事务控制‐‐>
<!‐‐配置事务管理器的bean‐‐>
<bean id="transactionManager" class="org.springframework.jdbc.datasourc e.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!‐‐开启基于注解的事务控制模式,依赖tx名称空间‐‐>
<tx:annotation‐driven transaction‐manager="transactionManager"></tx:annotation‐driven>
注:使用该标签的时候,一定要注意依赖的是tx名称空间的引用。
配置好之后,需要配合注解@Transactional注解使用。
@Transactional可以标记在类上,也可以标记在方法上。标记在类上时代表该类下的所有方法都运用上了事务;当标记在方法上时,则只是当前方法运用事务。当然也可以同时存在与类和方法上,这种情况以方法上的为准,如果方法上没有注解,则以类上的为准。
虽然@Transactional直接加在类上是更省事的,但是并不建议这么使用,写在方法上面控制的粒度更细,避免不必要的问题出现,影响开发效率。同时,@Transactional一般会存在于业务逻辑层中,在绝大多数情况下,只有业务逻辑层才会出现嵌套调用的情况。
2、事务配置的属性
isolation:设置事务的隔离级别
propagation:事务的传播行为
noRollbackFor:那些异常事务可以不回滚
noRollbackForClassName:填写的参数是全类名
rollbackFor:哪些异常事务需要回滚
rollbackForClassName:填写的参数是全类名
readOnly:设置事务是否为只读事务
timeout:事务超出指定执行时长后自动终止并回滚,单位是秒。
1)设置隔离级别
解决什么问题:在并发(同一时间,多个线程同时进行请求)情况下,对同一个数据进行读写操作时产生的问题。
会产生的问题:
a)脏读:表示一个事物能够读取到另一个事物中还未提交的数据。比如:某事物尝试插入记录A,此时该食物还未提交,然后另一个事务就读取到了记录A。
b)不可重复读:是指在一个事务内,多次读同一个数据,但读取到的结果不一样,会在本市无中产生数据不一致的问题。
c)幻读:指同一个事物内多次查询返回的结果集不一样。比如同一个事务A第一次查询时候有n条记录,但是第二次同等条件下查询就有m条数据了,这就好像产生了幻觉。发生幻读的原因也是另一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。
解决方式(也就是事务隔离级别):
未提交读(READ-UNCOMMITTED):最低隔离级别,事务未提交之前,就可以被其他食物读取到,可能产生:脏读、幻读、不可重复读。
已提交读(READ-COMMITTED):一个事务提交后才能被其他事务读取到,会造成幻读、不可重复读,能解决脏读问题。
可重复读(REPEATABLE-READ):默认隔离级别,保证多次读取同一数据时,其值都和事务开始时候的内容是一致的,禁止读取到别的食物为提交的数据,也会造成幻读,可以解决脏读和不可重复读。
序列化(SERIALIZABLE):代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
注:不可重复读和幻读诗有些相似的,区别在于前者只需要锁行,后者需要锁表,大家不要弄混了哦。
三、为什么要使用事务
首先,Spring时通过AOP对事务进行管理的,当在数据库执行多步操作时,其中一步出现数据异常时通过事务之行回滚,事务不是必须使用的,这取决于项目是需不需要做事务控制,当然,在大多数企业级项目中,都是需要的哈。他也是维护数据安全性的一种方式,像是在银行的项目中的转账服务,事务就是至关重要的,需要他的护航,避免金钱交易出现错差。