一、spring事务管理
1、 什么是事务
事务(Transaction)是多个操作数据库的步骤(CRUD)的集合,是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。达到保持数据完整性的作用。
2、 事务特点
1) 原子性
一个事务所有对数据库操作是一个最小单位,不可细分;要么执行,要么不执行
2) 隔离性
事务之间可以同时执行,不会互相干扰,是隔离的
3) 一致性
事务执行成功数据库变更,事务执行失败数据库不变更,即事务一致性
4) 持久性
事务执行成功,之后的结果是持久的,一直保持
3、 事务配置方式
1) 编程式事务
编程式事务指的是通过编码方式实现事务,需要配置文件添加配置,并且在编码中也需要配置,现在使用越来越少
2) 声明式事务
建立在AOP之上的。对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务;声明式事务配置一般有五种(abcde),两种配置方式较为常用:我喜欢用第一种
a) 使用AOP的方式实现事务配置
i. aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。
首先应该特别注意的是id的命名,同样由于每个模块都有自己事务切面,所以我觉得初步的命名规则因为 all+模块名+ServiceMethod。而且每个模块之间不同之处还在于以下一句:
expression="execution(* com.test.testAda.test.model.service.*.*(..))"
其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数。
ii. aop:advisor标签主要将事务属性配置和开启事务类进行关联
iii. tx:attributes标签主要是配置事务的方法属性类型,name=add*中表示事务中所有以add开头的方法。
b) 注解式配置
i. Spring-mybatis
ii. Spring-hibernata
iii. 注意@Transaction注解的使用
这个注解只能使用在public方法上,别的不会报错,但是没有效果;如果这个注解放在类上,类里面的所有public方法都会有效。
iv. 全注解的使用方式
v. 注解中属性详解
Propagation是传播属性,REQUIRED代表使用当前开启事务;rollbackFor=Exception.class代表出现异常回滚,可以指定多个异常;
Timeout =1 事务的超时性;
Isolation代表事务隔离级别,上面的是默认;
配置readOnly=true表示当前事务为只读事务,如果为false为可读写,默认是false。
vi. 注解位置
注解最好放在具体的类或者方法上,不要放在接口上,因为注解不具有继承性,所以如果读取不到注解信息,将不会读取到相应对象二进行事务配置。
c) 每个bean都有一个代理
https://blog.csdn.net/hjm4702192/article/details/17277669
d) 所有bean共享一个代理基类
https://blog.csdn.net/hjm4702192/article/details/17277669
e) 使用拦截器
https://blog.csdn.net/hjm4702192/article/details/17277669
4、 事务隔离级别
事务隔离级别指的是多个并发事务之间的隔离程度
1) ISOLATION_DEFAULT
此种隔离级别是事务管理默认配置的,使用数据库的默认隔离级别,上面的配置中就是使用此种级别,下面的四种级别与jdbc的相对应。
2) ISOLATION_READ_UNCOMMITTED
未提交读。允许其他事务可以看到本事务未提交的数据,可造成脏读、幻读和不可重复读
3) ISOLATION_READ_COMMITTED
提交读。其他事务只能读取到本事务提交后的数据,本事务不提交,其他事务无法读取到本事务数据,可防止脏读,可能出现幻读和不可重复读
4) ISOLATION_REPEATABLE_READ
可重复度。保证事务不提交就不会读取到其数据,防止脏读和不可重复读,可能发生幻读。
5) ISOLATION_SERIALIZABLE
可串行化。牺牲效率顺序执行事物,如果事物执行异常,其他事务阻塞。防止脏读,幻读和不可重复。
5、 事务传播属性
1) PROPAGATION_REQUIRED
使用当前事务,如果当前无事务,新建一个事务
2) PROPAGATION_SUPPORTS
使用当前事务,如果当前无事务,使用非事务方式执行
3) PROPAGATION_MANDATORY
使用当前事务,如果当前无事务,抛出异常
4) PROPAGATION_REQUIRES_NEW
每次执行新建事务,如果当前存在事务,将当前事务挂起
5) PROPAGATION_NOT_SUPPORTED
以非事务方式执行,如果当前存在事务,将当前事务挂起
6) PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,抛出异常
7) PROPAGATION_NESTED
嵌套类事务,如果当前存在事务,则在当前事务内新建事务并执行,如果当前无事务,与第一条同样方式执行
二、数据库隔离级别
1、未提交读
(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
2、提交读
(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
3、可重复度
(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
4、可串行化
(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
三、数据异常
1、脏读
A事务正在添加zhangsan信息,但是还没提交,数据库就已经能读取到张三信息。
2、幻读
多个事务同时修改同一条记录,事务之间不知道彼此存在,当事务提交之后,后面的事务修改的数据将会覆盖前事务,前一个事务就像发生幻觉一样
例如:同时修改某行数据
事务A将姓名字段修改为zhangsan,
事务B将姓名字段修改为lisi
事务提交,事务B将覆盖A数据,也就是zhangsan丢失。
3、不可重复读
在A事务中,两次读取同一个数据,在A事务第一次读取数据之后,B事务修改这条数据,当A事务再次读取这条数据之后,获取到的结果与第一次读到的不一致。(读取到的数据不一致)
事务完成操作之前,不允许其他事务进行操作,可避免