Spring中的事务管理及实现方式解析
作者:saint_motel
1、事务认识
大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销。
Spring事务管理基于底层数据库本身的事务处理机制。
数据库事务的基础,是掌握Spring事务管理的基础。
事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。
- A:原子性(Atomicity),一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。就像你买东西要么交钱收货一起都执行,要么发不出货,就退钱。
- C:一致性(Consistency),事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。
- I:隔离性(Isolation),指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。打个比方,你买东西这个事情,是不影响其他人的。
- D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须***保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。打个比方,你买东西的时候需要记录在账本上,即使老板忘记了那也有据可查。
2、事务的传播特性
事务传播行为就是多个事务方法调用时,如何定义方法间事务的传播。
Spring定义了7中传播行为:
(1)propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是Spring默认的选择。
(2)propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
(3)propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
(4)propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
(5)propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
(6)propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
(7)propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作。
3、事务的隔离级别
(1)read uncommited:是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
(2)read commited:保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。
(3)repeatable read:这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。
(4)serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读
脏读、不可重复读、幻象读概念说明:
a. 脏读:指当一个事务正字访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
b. 不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
c. 幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)
4、事务几种实现方式(两种方式)
编程式事务管理(目前在开发中很少使用)
使用步骤
1. 配置数据库事务管理 DataSourceTransactionManager
<!--配置事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
2. 配置数据库事务管理模板
<!--配置事务管理模板--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <!--配置事务管理--> <property name="transactionManager" ref="transactionManager"></property> </bean>
3. 在Service层中注入数据库事务管理模板
<!--配置Service--> <bean id="accountService" class="top.wintp.springtx.demo1.service.AccountServiceImpl"> <!--配置事务的管理模板类--> <property name="transactionTemplate" ref="transactionTemplate"/> <property name="accountDao" ref="accountDao"/> </bean>
4. 在需要执行事务的位置调用transactionTemplate的execute()方法
transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { //执行你的逻辑 } });
声明式事务管理
声明式事务管理方式一:基于TransactionProxyFactoryBean的方式 (不常用)
使用步骤
1.配置事务管理 DataResourceTransactionManager
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
2.配置事务代理类
<!--配置事务代理类--> <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!--配置事务管理器--> <property name="transactionManager" ref="transactionManager"/> <!--配置代理目标类--> <property name="target" ref="accountService"></property> <!-- 配置事物的基本属性 必须配置 --> <property name="transactionAttributes"> <props> <!-- prop 格式 key:方法名 或者 方法 * 例如 insert* 值的格式: PROPAGATION:事物的传播行为 ISOLATION:事物的隔离级别 readOnly:只读 -Exception:发生哪些异常,回滚事物 默认任何异常都回滚 +Exception:发生哪些异常,不回滚事物 --> <prop key="transfMoney">PROPAGATION_REQUIRED</prop> </props> </property> </bean>
3.引用代理类 使用代理目标类来接收
@Resource(name = "accountServiceProxy") private AccountService mAccountService;
声明式事务管理方式二:基于AspectJ的XML方式
1.配置事务管理类
<!--配置事务的管理类--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
2.配置事务的增强
<!--配置事务的增强--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
3.配置AOP – 切点和切面
<!--配置AOP--> <aop:config> <!--配置切入点--> <aop:pointcut id="pointcut1" expression="execution(* top.wintp.springtx.demo6.service.AccountService+.*(..))"/> <!--配置切面--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/> </aop:config>
声明式事务管理方式三:基于注解的方式(常用)
1.配置事务管理器
<!--配置事务的管理类--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
2.开启事务注解
<!--开启事务注解 --> <tx:annotation-driven transaction-manager="transactionManager"/>
3.在需要事物管理的类上添加注解
@Transactional(propagation = Propagation.REQUIRED)
到此这篇关于Spring中的事务管理及实现方式解析的文章就介绍到这了,更多相关Spring事务管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!