首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Transaction 注解

Transaction 注解

作者头像
Remember_Ray
发布2020-08-03 23:18:35
7470
发布2020-08-03 23:18:35
举报
文章被收录于专栏:Ray学习笔记Ray学习笔记

@Transaction 参考 Transaction事务属性 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法

Spring 中 @Transactional 配置

引入命名空间

在 Spring 配置文件中 引入 <tx:> 命名空间

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"
	default-lazy-init="true">

重点关注

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

添加事务管理器

<!-- 配置 Annotation 驱动,扫描@Transactional注解的类定义事务  -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

@Transactional的属性

属性

类型

描述

value

String

可选的限定描述符,指定使用的事务管理器

propagation

enum: Propagation

可选的事务传播行为设置

isolation

enum: Isolation

可选的事务隔离级别设置

readOnly

boolean

读写或只读事务,默认读写

timeout

int (in seconds granularity)

事务超时时间设置

rollbackFor

Class对象数组,必须继承自Throwable

导致事务回滚的异常类数组

rollbackForClassName

类名数组,必须继承自Throwable

导致事务回滚的异常类名字数组

noRollbackFor

Class对象数组,必须继承自Throwable

不会导致事务回滚的异常类数组

noRollbackForClassName

类名数组,必须继承自Throwable

不会导致事务回滚的异常类名字数组

Spring 中 @Transactional 的传播行为和隔离级别

不同的位置使用

  1. 标注在类前:表示类中的所有方法都进行事务处理
  2. 标注在接口、实现类的方法前:表示方法进行事务处理

事务传播行为

注释

作用

@Transactional(propagation=Propagation.REQUIRED)

如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

@Transactional(propagation=Propagation.NOT_SUPPORTED)

容器不为这个方法开启事务

@Transactional(propagation=Propagation.REQUIRES_NEW)

不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务

@Transactional(propagation=Propagation.MANDATORY)

必须在一个已有的事务中执行,否则抛出异常

@Transactional(propagation=Propagation.NEVER)

必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)

@Transactional(propagation=Propagation.SUPPORTS)

如果其他bean调用这个方法,在其他bean中声明事务,那就用事务。如果其他bean没有声明事务,那就不用事务

事务超时设置

@Transactional(timeout=30) //30秒超时

事务隔离级别

注释

作用

@Transactional(isolation = Isolation.READ_UNCOMMITTED)

读取未提交数据(会出现脏读, 不可重复读) 基本不使用

@Transactional(isolation = Isolation.READ_COMMITTED)

读取已提交数据(会出现不可重复读和幻读)

@Transactional(isolation = Isolation.REPEATABLE_READ)

可重复读(会出现幻读)

@Transactional(isolation = Isolation.SERIALIZABLE)

串行化

  1. 脏读 : 一个事务读取到另一事务未提交的更新数据。
  2. 不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 后续读取可以读到另一事务已提交的更新数据。
  3. 可重复读 : 在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据。
  4. 幻读 : 一个事务读到另一个事务已提交的insert数据。

REQUIRED 与 REQUIRED_NEW 解读

在上面的事务传播行为的六种情况中,最难以理解的,并且容易在transaction设计时出现问题的是 REQUIREDREQURED_NEW 这两者的区别。当程序在某些情况下抛出异常时,如果对于这两者不够了解,就可能很难发现而且解决问题。

场景一

ServiceA.java:
public class ServiceA {
    @Transactional
    public void callB() {
        serviceB.doSomething();
    }
}


ServiceB.java
public class ServiceB {
    @Transactional
    public void doSomething() {
        throw new RuntimeException("B throw exception");
    }
}

这种情况下,我们只需要在调用 ServiceA.callB 时捕获 ServiceB 中抛出的运行时异常,则transaction就会正常的rollback。

场景二

在保持场景一中 ServiceB 不变,在 ServiceA 中调用 ServiceBdoSomething 时去捕获这个异常,如下:

public class ServiceA {
    @Transactional
    public void callB() {
        try {
            serviceB.doSomething();
        } catch (RuntimeException e) {
            System.err.println(e.getMessage());
        }
    }
}

这个时候,我们再调用 ServiceAcallB。程序会抛出这样一个异常信息

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as  rollback-only

原因是什么呢?

因为在 ServiceAServiceB 中的 @Transactional

propagation都采用的默认值:REQUREID

根据我们前面讲过的REQUIRED特性,当 ServiceA 调用 ServiceB 的时候,他们是处于同一个transaction中。

ServiceB中抛出了一个异常以后,ServiceB会把当前的transaction标记为需要rollback。但是ServiceA中捕获了这个异常,并进行了处理,认为当前transaction应该正常commit。此时就出现了前后不一致,也就是因为这样,抛出了前面的UnexpectedRollbackException

场景三

在保持场景二中ServiceA不变,修改ServiceB中方法的propagation配置为REQUIRES_NEW,如下:

public class ServiceB {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void doSomething() {
        throw new RuntimeException("B throw exception");
    }
}

此时,程序可以正常的退出了,也没有抛出UnexpectedRollbackException。原因是因为当ServiceA调用ServiceB时,serviceBdoSomething是在一个新的transaction中执行的。

所以,当 doSomething抛出异常以后,仅仅是把新创建的transaction rollback了,而不会影响到ServiceA的transaction。ServiceA就可以正常的进行commit。

当然这里把ServiceAServiceB放在两个独立的transaction是否成立,还需要再多多考虑你的业务需求。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-04-12|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring 中 @Transactional 配置
    • 引入命名空间
      • 添加事务管理器
      • @Transactional的属性
      • Spring 中 @Transactional 的传播行为和隔离级别
        • 不同的位置使用
          • 事务传播行为
            • 事务超时设置
              • 事务隔离级别
              • REQUIRED 与 REQUIRED_NEW 解读
                • 场景一
                  • 场景二
                    • 场景三
                    相关产品与服务
                    容器服务
                    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档