SpringJDBC中的事务

21 篇文章 0 订阅

SpringJDBC中的事务

Spring中事务分为三种类型 :
  • 编程式事务
  • 声明式事务
  • 注解形式事务
一、编程式事务

在需要执行事务的类中,声明一个DataSourceTransactionManager事务管理器transactionManager,在需要使用事务的方法中要做三个步骤 :

  1. 定义一个DefaultTransactionDefinition事务默认的标准配置definition,其父类为TransactionDefinition;
  2. 开始一个事务,执行transactionManager.getTransaction(definition)返回TransactionStatus事务状态status;
  3. 把要用到事务的部分用try-catch包裹起来,若执行成功则 执行transactionManager.commit(status)进行事务提交,若出现异常则执行transactionManager.rollback(status)进行事务回滚,异常可根据具体业务需求选择是否抛出。
二、声明式事务

声明式事务主要依赖aop进行实现,首先要在applicationContext.xml中引入对应的命名空间。然后进行事务通知配置,决定哪些方法使用事务,哪些方法不使用事务,如下:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>        
        <!-- 目标方法名为batchImport时,启用声明式事务,成功提交,运行时异常回滚 --> 
        <tx:method name="batchImport" propagation="REQUIRED"/>        
        <tx:method name="batch*" propagation="REQUIRED"/>        
        <!-- 设置所有findXXX方法不需要使用事务 -->
        <tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
        <tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

然后通过aop定义声明式事务的作用范围,如下:

<aop:config>
    <aop:pointcut id="pointcut" expression="execution(* com.flagship..*Service.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
三、注解形式事务

使用@Transactional注解,@Transactional可以放在类上,也可以放在方法上,放在类上则整个类中的方法都使用该事务,放在方法上则作用在对应的方法上,当类和方法上都存在@Transactional时,执行方法上的@Transactional。@Transactional存在几个属性:

  • readOnly:该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。
  • rollbackFor:该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。
  • rollbackForClassName:该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。
  • noRollbackFor:该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。
  • noRollbackForClassName:该属性用于设置不需要进行回滚的异常类名称数组。
  • timeout:该属性用于设置事务的超时秒数,默认值为-1表示永不超时。
  • propagation:该属性用于设置事务的传播行为。
事务传播行为:

REQUIRED:没有事务就创建一个事务,如果外围有一个事务,则嵌套到 外围的事务中,即当A方法有事务时,A当中执行了BC两个方法,他们都各自有事务,当执行完B时,因为事务被嵌套到了A的事务当中,所以B的事务没有提交。当此时出现了异常,整个A过程事务所包裹的方法都会被回滚 ,即BC当中的事务都不会生效,因为他们都被嵌套进了A的事务当中。
REQUIRED_NEW:与REQUIRED相似,没有事务就创建一个事务,如果外围有一个事务,则先将外围的事务挂起,即事务之间是独立的,不会存在嵌套。
NOT_SUPPORTED:以非事务方式执行。如有A方法使用了事务,A方法中调用了B方法,如果B方法没有设置NOT_SUPPORTED,则B方法出现异常会导致A方法的进行事务回滚,如果有设置NOT_SUPPORTED,则B方法出现异常时不会导致A方法发生事务回滚。
SUPPORTS:如果外层有事务,则使用外层的事务,如果没有则按非事务方式执行(有点随大流的意思)。
MANDATORY:如果外层没有事务,则抛出异常。
NEVER:以非事务方式执行,如果外层有事务,则抛出异常。
NESTED:与REQUIRED相似。假设A方法有事务,然后调用了B方法,如果B方法不是使用了NESTED,那么当B方法出现异常时,即使在A方法中调用B方法的地方进行了try-catch且异常不抛出,也依然会导致A方法的整个事务进行回滚。但如果B方法使用了NESTED,那么即便是在B方法中出现了异常,只要在A的try-catch调用B部分的地方不把异常抛出,则不会导致事务回滚。即NESTED可以不影响外围的事务。

事务隔离级别
  • @Transactional(isolation = Isolation.READ_UNCOMMITTED)读取未提交数据(会出现脏读, 不可重复读) 基本不使用
  • @Transactional(isolation = Isolation.READ_COMMITTED)读取已提交数据(会出现不可重复读和幻读)
  • @Transactional(isolation = Isolation.REPEATABLE_READ)可重复读(会出现幻读)
  • @Transactional(isolation = Isolation.SERIALIZABLE)串行化
什么是脏读、幻读、不可重复读?
  • 脏读 : 一个事务读取到另一事务未提交的更新数据。
  • 不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据。
  • 幻读 : 一个事务读到另一个事务已提交的insert数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JackieLeeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值