Spring 声明式事务学习总结

Spring JdbcTemplate

在spring中为了更加方便的操作JDBC,在JDBC的基础之上定义了一个抽象层,目的是为不同类型的JDBC操作提供模板方法,也就是对不同数据库提供不同模板方法,每个模板方法都能控制整个过程,并允许覆盖过程中的特定任务,通过这种方式,可以尽可能保留灵活性,将数据库存取的工作量降到最低。

Spring事物

Spring事务的本质其实就是通过spring来操作数据库的事务,数据库没有事务支持的话,spring是无法提供事务功能的。Spring事务使用AOP的机制实现,会在@Transactional注解修饰的方法前后分别织入开启事务的逻辑,以及提交或回滚的逻辑。

ACID属性

原子性(Atomicity) : 事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
一致性(Consistent) : 在事务开始和完成时,数据都必须保持一致状态。
隔离性(Isolation) : 事务处理过程中的状态对其他事务是不可见的。
持久性(Durable) : 事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。

Spring在事务控制方面,主要分为两类

编程式事务:在代码中直接加入处理事务的逻辑,显式的调用beginTransaction()、commit()、rollback()等事务管理相关的方法。

声明式事物:在方法的外部添加注解或者直接在配置文件中定义,将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。spring的AOP可以完成此功能:事务管理代码的固定模式作为一种横切关注点,通过AOP方法模块化,进而实现声明式事务。

声明式事务配置

XML方式:

 <!--jdbcTemplate.xml-->
  <!--配置事务管理器的bean-->
   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"></property>
   </bean>
   <!--基于xml配置的事务:依赖tx名称空间和aop名称空间
       1、spring中提供事务管理器(切面),配置这个事务管理器
       2、配置事务方法
       3、告诉spring哪些方法是事务方法(事务切面按照我们的切入点表达式去切入事务方法)-->
   <bean id="bookService" class="cn.test.service.BookService"></bean>
   <aop:config>
       <aop:pointcut id="txPoint" expression="execution(* cn.tulingxueyuan.service.*.*(..))"/>
       <!--事务建议:advice-ref:指向事务管理器的配置-->
       <aop:advisor advice-ref="myAdvice" pointcut-ref="txPoint"></aop:advisor>
   </aop:config>
   <tx:advice id="myAdvice" transaction-manager="transactionManager">
       <!--事务属性-->
       <tx:attributes>
           <!--指明哪些方法是事务方法-->
           <tx:method name="*"/>
           <tx:method name="checkout" propagation="REQUIRED"/>
           <tx:method name="get*" read-only="true"></tx:method>
       </tx:attributes>
   </tx:advice>

注解方式:@Transactional

使用此注解需要在配置类上加@EnableTransactionManagement注解来开启注解驱动
并且需保证已经配置了至少一个PlatformTransactionManager的Bean,否则会报错
@Transactional   标记在类上面表示当前类所有方法都有事务控制
@Transactional   标记在方法则只是当前方法有事务控制
​@Transactional​​​默认回滚的的异常是​​RuntimeException​,如果需要支持回滚​​Exception​​​异常要用​​@Transactional(rollbackFor = Exception.class)​​
如果类和方法都存在@Transactional会以方法的为准。如果方法上面没有@Transactional会以类上面的为准
建议:
@Transactional写在方法上面,控制粒度更细,   
@Transactional写在业务逻辑层上,因为只有业务逻辑层才会有嵌套调用的情况。
事务配置的属性
isolation:设置事务的隔离级别
propagation:事务的传播行为
noRollbackFor:定义哪些异常事务可以不回滚
noRollbackForClassName:填写的参数是全类名
rollbackFor:定义哪些异常事务需要回滚
rollbackForClassName:填写的参数是全类名
readOnly:设置事务是否为只读事务		
timeout:事务超出指定执行时长后自动终止并回滚,单位是秒
Spring的事务传播机制

当出现多个事务嵌套的场景发生时,Spring事务的处理会变得复杂一些,需要考虑嵌套事务下的提交顺序,以及回滚顺序,对此,Spring提供了多种的传播机制:

REQUIRED:默认值,支持当前事务,如果没有事务会创建一个新的事务
SUPPORTS:支持当前事务,如果没有事务的话以非事务方式执行
MANDATORY:支持当前事务,如果没有事务抛出异常
REQUIRES_NEW:创建一个新的事务并挂起当前事务
NOT_SUPPORTED:以非事务方式执行,如果当前存在事务则将当前事务挂起
NEVER:以非事务方式进行,如果存在事务则抛出异常
NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与REQUIRED类似的操作

当子方法事务的传播机制为REQUIRED时:
请添加图片描述
当子方法事务的传播机制为NESTED时:
请添加图片描述

Spring事务嵌套默认传播机制下最佳实践

1、外部方法无事务注解,内部方法添加REQUIRED事务传播类型:

内部方法抛出异常,内部方法事物回滚,不会影响外部方法,外部方法会执行成功。

2、外部方法添加REQUIRED事务传播类型,内部方法无事务注解:

内部方法抛出异常,会影响外部方法的执行,导致外部事务回滚。

3、外部方法、内部方法都添加REQUIRED事务传播类型:

内部方法抛出异常,会影响外部方法的执行,内外事务都回滚。

4、外部方法添加REQUIRED事务传播类型,内部方法添加NOT_SUPPORTED事务传播类型

内部方法抛出异常,外部方法会回滚,内部方法不会回滚;
外部方法抛出异常,内部方法执行成功,内部方法会提交;
内部方法永远不会回滚。
Spring事务失效场景

1、数据库不支持事务
2、事务方法未被Spring管理,也就是事务方法所在的类没有加载到Spring IOC容器中
3、方法没有被public修饰
4、方法的事务传播类型不支持事务(NOT_SUPPORTED、NEVER)。
5、使用了try-catch代码块将异常捕捉了,没有向上抛出异常,事务不会回滚。
6、标注错误的异常类型,例如Spring事务默认回滚类型是RuntimeException类型,如果没有制定回滚的类型,抛出的错误不是RuntimeException类型,则无法回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值