这篇博文主要是写关于Spring事务相关,进行一个总结,本博文避开Spring中的API,尽量使用文字叙述。
-
初识,什么是事务(Transaction)?
说完事务的概念,我们可以看看,事务的几个基本特向,即ACID
-
那么,什么是事务的ACID特性?
-
原子性(Atomicity):
- 原子,即不可再分。在原子性中,事务被当做一个不可分割的整体,包含在其中的操作要么全部执行,要么全部不执行。
- 事务在执行过程中,如果发生错误会被回滚到事务开始状态,就像这个事务从来没有执行过一样。
-
一致性(Consistency):
- 事务的执行结果,必须I使得数据库从一个正确的状态转换成另一个正确的状态,且数据库完整性约束没有被破坏。
-
隔离性(Isolation):
- 一个事务的执行不能被其他事务所干扰,即在事务正确提交之前,不允许把该事务对数据的任何改变提供给其他事务,且事务处理过程中的中间状态对外部是不可见的。
- 多个事务并发执行,一个事务的执行不应该影响其他事务的执行。
- 主要强调,并发环境。
-
持久性(Durability):
- 一个事务一旦成功提交,那么对数据库中的数据改变就像永久性的。即使在数据库系统遇到故障时,也不会丢失提交事务的操作。
说完事务的四个特性,相信读者对事务有了一个基本的概念。那么,且看Spring的事务。
-
-
在Spring中事务中,主要分为编程式事务和声明式事务。
-
编程式事务
-
程序员手动控制事务,就叫做编程式事务。
-
比如,在JDBC中,编程式事务可以这样写:
// JDBC事务 Connection conn = getConnection(); conn.setAutoCommit(false); // 业务实现 do somethng.... if 正常 conn.commit(); if 失败 或 异常 conn.rollback();
-
使用编程式事务,可以把事务进行细粒度化。即,可以对指定的方法,或者方法中的某几行进行事务控制。但是粒度降低的同时,开发起来比较繁琐,因为每次都回去手动开启、提交、回滚。
-
当然,编程事务可以缓解声明式事务的尴尬,因为并不是每个需求,都要使用声明式事务。有时候,少量的手动编写事务,可能效果更佳。
-
-
声明式事务
- Spring的强大之一便是声明式事务管理。基于AOP编程,其本质是在目标方法执行前后进行拦截,即在方法开始之前开启一个事务,在方法结束后根据执行情况进行提交或回滚。
- 声明式事务实现方式一般是两种:XML和注解。
-
声明式事务之XML实现
<!-- 配置事物拦截方法,定义哪些方法需要进行事务管理 --> <tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager"> <tx:attributes> <tx:method name="get*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="*" read-only="false" /> </tx:attributes> </tx:advice> <!-- Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务管理配置 --> <aop:config> <aop:pointcut expression="execution(* com.xx.service.*.*(..))" id="pt" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt" /> </aop:config>
-
声明式事务之注解实现:@Transcationl
- 修饰一个方法,即表明当前方法应用Spring声明式事务。
- 修饰一个类,即表明类的所有方法应用Spring声明式事务。
- 修饰一个父类,即子类调用父类方法的时候应用Spring声明式事务。
-
声明式事务的实现原理,读者只要知道以下公式:
- 声明式事务 = AOP + 环绕通知 (开启与提交)+ 异常通知(异常回滚)
- 其实环绕和异常通知都属于AOP,对于笔者来说更容易记忆。在工程中使用事务的时候,比如在Service层,读者们一定要将异常向上抛出(throw),而不能自己捕获(try-cache)。原因,读者可以去了解一下环绕通知相关知识点。
说完Spring的事务,接下来主要是事务的传播特性。
-
-
什么是Spring的事务传播特性?
-
传播特性,即一个具有事务的方法被嵌套到另外一个方法的时候,事务如何执行。
-
在springAPI中,事务特性有以下几种:
- PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
- PROPAGATION_SUPPORTS :支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW :新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED :以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
参考链接:
-