Spring Boot之@Transactional

Springboot之@Transactional事务注解原理详解 文章目录注册事务切面逻辑根据切面逻辑生成代理类总结 @Transactional注解的逻辑是通过动态代理来实现的,而生成这个动态代理类分成了两步: 1、向spring容器注册事务相关的切面逻辑 2、根据切面逻辑生成动态代理 下面围绕这两点来看下Springboot里的实现原理 注册事务切面逻辑 切面逻辑里有三个概念: Pointcut:负责告诉spring容器哪个类需要增强 Advise:具体的切面逻辑,这里就是根据异常进行commit或者回滚的相关逻辑 Advisor:封装了Advise和Pointcut 阅读详情

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。

  • 编程式事务指的是通过编码方式实现事务;
  • 声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。

声明式事务有两种方式:

  • 配置文件(xml)
  • @Transactional 注解

本文将着重介绍基于 @Transactional 注解的事务管理。

需要明确几点:

  • 默认配置下 Spring 只会回滚运行时、未检查异常(继承自 RuntimeException 的异常)或者 Error
  • @Transactional 注解只能应用到 public 方法才有效

以下的示例使用的是 mybatis,所以 spring boot 会自动配置一个 DataSourceTransactionManager,我们只需在方法(或者类)加上 @Transactional 注解,就自动纳入 Spring 的事务管理了。

简单的使用方法

1、在启动类上添加@EnableTransactionManagement,开启事务注解

@SpringBootApplication
@EnableTransactionManagement// 开启事务注解
public class SpringBootSsmApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringBootSsmApplication.class, args);
	}
}

2、在配置类里将PlatformTransactionManager加入容器

@Configuration
public class DruidConfig {
    // 与属性文件里的属性绑定
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource(){
        return new DruidDataSource();
    }
    // 注册事务管理器
    @Bean
    public PlatformTransactionManager transactionManager(){
        return new DataSourceTransactionManager(druidDataSource());
    }
}

3、在方法加上 @Transactional 注解

如下有一个保存用户的方法,加入 @Transactional 注解,使用默认配置,抛出异常之后,事务会自动回滚,数据不会插入到数据库。

@Transactional
@Override
public void save() {
    User user = new User("服部半藏");
    userMapper.insertSelective(user);

    if (true) {
        throw new RuntimeException("save 抛异常了");
    }
}

属性介绍

value 和 transactionManager 属性

这两个是一样的意思。当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器。

propagation 属性

事务的传播行为,默认值为 Propagation.REQUIRED。

可选的值有:

  • Propagation.REQUIRED

如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。

  • Propagation.SUPPORTS

如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。

  • Propagation.MANDATORY

如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。

  • Propagation.REQUIRES_NEW

重新创建一个新的事务,如果当前存在事务,暂停当前的事务。

  • Propagation.NOT_SUPPORTED

以非事务的方式运行,如果当前存在事务,暂停当前的事务。

  • Propagation.NEVER

以非事务的方式运行,如果当前存在事务,则抛出异常。

  • Propagation.NESTED

和 Propagation.REQUIRED 效果一样。

isolation 属性

事务的隔离级别,默认值为 Isolation.DEFAULT。

可选的值有:

  • Isolation.DEFAULT:使用底层数据库默认的隔离级别。
  • Isolation.READ_UNCOMMITTED
  • Isolation.READ_COMMITTED
  • Isolation.REPEATABLE_READ
  • Isolation.SERIALIZABLE

timeout 属性

事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。

readOnly 属性

指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。

rollbackFor 属性

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。

noRollbackFor 属性

抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。

propagation 属性代码示例

比如如下代码,save 方法首先调用了 method1 方法,然后抛出了异常,就会导致事务回滚,如下两条数据都不会插入数据库。

@Transactional(propagation = Propagation.REQUIRED)
@Override
public void save() {

    method1();

    User user = new User("服部半藏");
    userMapper.insertSelective(user);

    if (true) {
        throw new RuntimeException("save 抛异常了");
    }
}

public void method1() {
    User user = new User("宫本武藏");
    userMapper.insertSelective(user);
}

现在有需求如下,就算 save 方法的后面抛异常了,也不能影响 method1 方法的数据插入。或许很多人的想法如下,给 method1 页加入一个新的事务,这样 method1 就会在这个新的事务中执行,原来的事务不会影响到新的事务。比如 method1 方法上面再加入注解 @Transactional,设置 propagation 属性为 Propagation.REQUIRES_NEW,代码如下。

@Transactional(propagation = Propagation.REQUIRED)
@Override
public void save() {

    method1();

    User user = new User("服部半藏");
    userMapper.insertSelective(user);

    if (true) {
        throw new RuntimeException("save 抛异常了");
    }
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void method1() {
    User user = new User("宫本武藏");
    userMapper.insertSelective(user);
}

结果并不是预期那样,其实两个方法都是处于同一个事务中,method1 方法并没有创建一个新的事务。

在默认的代理模式下,只有目标方法由外部调用,才能被 Spring 的事务拦截器拦截。在同一个类中的两个方法直接调用,是不会被 Spring 的事务拦截器拦截,就像上面的 save 方法直接调用了同一个类中的 method1方法,method1 方法不会被 Spring 的事务拦截器拦截。可以使用 AspectJ 取代 Spring AOP 代理来解决这个问题,但是这里暂不讨论。

为了解决这个问题,我们可以新建一个类。

@Service
public class OtherServiceImpl implements OtherService {

    @Autowired
    private UserMapper userMapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void method1() {
        User user = new User("风魔小太郎");
        userMapper.insertSelective(user);
    }
}

然后在 save 方法中调用 otherService.method1 方法

@Autowired
private OtherService otherService;

@Transactional(propagation = Propagation.REQUIRED)
@Override
public void save() {

    otherService.method1();

    User user = new User("服部半藏");
    userMapper.insertSelective(user);

    if (true) {
        throw new RuntimeException("save 抛异常了");
    }
}

结果,otherService.method1 方法的数据插入成功,save 方法的数据未插入,事务回滚。

首先创建了 save 方法的事务,由于 otherService.method1 方法的 @Transactional 的 propagation 属性为 Propagation.REQUIRES_NEW ,所以接着暂停了 save 方法的事务,重新创建了 otherService.method1 方法的事务,接着 otherService.method1 方法的事务提交,接着 save 方法的事务回滚。这就印证了只有目标方法由外部调用,才能被 Spring 的事务拦截器拦截。


转载自《Spring Boot 中使用 @Transactional 注解配置事务管理》


@transactional注解在什么情况下会失效,为什么。

详情请看《@transactional注解在什么情况下会失效,为什么。》

SpringBoot系列:事务管理器Transactional 一、事务 事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)... 阅读详情

相关推荐

Spring Boot 中使用 @Transactional 注解配置事务管理

下面分别介绍一下的几个属性。

m0_74825003的博客 1632

【Java 基础】SpringBoot 中 @Transactional 注解的使用与实践

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。本篇只说明声明式注解。 事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)。 事务的四大特性:只需在方法加上 @Transactional 注解就可以了。如下有一个保存数据的方法,加入 @transactiona

yuxiangdeming的博客 4万+

Spring Boot 事务@Transactional的实现原理

@Transactional 涉及到两个方面,一个是数据的持久化,第二个是数据库的事务。关于持久化以及事务不做赘述。 在持久化中涉及到了实体管理器EntityManager类,该类通过@PersistenceContext进行注解,标识只注入一次实体管理器,但是因为EntityManager是一个interface,所以它的注入是通过感知上下文内容进行注入的,因此是存在的问题的,所...

lee_master的博客 1446

SpringBoot - @Transactional注解详解

Spring中的@Transactional注解,基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷的解决在开发中碰到的问题,@Transactional 的事务开启 ,或者是基于接口的或者是基于类的代理被创建。Spring为了更好的支撑数据库操作,在框架中支持了两种事务管理的方式:编程式事务和声明式事务,能够保证作单个逻辑工作单元执行的一系列操作,要么同时成功,要么同时失败。

记录并分享 3900

深入解析Spring Boot中的`@Transactional`注解

在Spring Boot开发中,数据库事务管理是一个至关重要的环节。`@Transactional`注解是Spring框架提供的一个强大工具,能够帮助开发者方便地管理事务。本文将深入解析`@Transactional`注解的工作原理、使用方式以及注意事项,并结合实际应用场景,帮助开发者更好地掌握这一工具。

fudaihb的博客 3877

spring boot注解@Transactional失效

引言 数据库事务,将有限系列的执行命令作为单个逻辑执行单元,单元内的任务要么全部成功,要么全部失败。 起因 由于业务逻辑需要,操作要么全部成功,要么全部失败。于是,抽出一个公共的service对数据库进行增删改操作。在执行这个方法的时候发现最后一次的操作失败了之后,前面的所有操作都成功了,没有回滚。 如何排查事务失效的原因 当@Transactiona...

隔壁老瓦的专栏 1958

Spring Boot 中 @Transactional 注解全面解析

Transactional注解是 Spring Boot 中实现事务管理的强大工具,它简化了事务处理的代码,提高了开发效率。通过合理使用@Transactional注解和事务传播机制,可以确保数据的一致性和完整性。在使用过程中,需要注意异常处理、事务方法的访问修饰符以及事务方法内部调用等问题,以避免出现意想不到的结果。希望本文能帮助开发者深入理解和正确使用@Transactional注解,提升 Spring Boot 应用开发的质量和效率。

qq_48131648的博客 1254

保姆级教程:在Ubuntu 20.04上搞定PX4飞控与T265的视觉定位(附避坑指南)

本文提供在Ubuntu 20.04上配置PX4飞控与T265视觉定位系统的详细教程,涵盖驱动安装、ROS与MAVROS桥接、PX4参数调优及故障排查。通过实测验证的步骤和避坑指南,帮助开发者实现厘米级精度的视觉定位,特别适合室内无人机应用。

weixin_29038155的博客 248

Spring Boot教程之十六:使用 @Transactional 注释进行事务管理

如果事务成功,则提交对数据库所做的更改,如果任何事务失败,则对该特定事务所做的所有更改都可以回滚,这将确保数据库保持一致状态。在这种情况下,spring 将用户信息存储在临时内存中,然后检查付款信息,如果付款成功,则它将完成事务,否则它将回滚事务,并且用户信息将不会存储在数据库中。我们将地址对象初始化为空并请求应用程序,我们在数据库中创建了一名员工,但地址信息却没有,因为我们收到了空指针异常。为此,我们将创建两个类。现在,我们将从数据库中删除我们的表并再次运行我们的应用程序,并请求应用程序创建一个员工。

潜洋的专栏 1735

【记录】游戏体验报告怎么写(自我成长篇)

2019年3月更新: 这个倒是不用推翻,我个人虽然写的东西还是有一些偏差的,但是“表哥”说的倒是没毛病的,这篇主要是为了记录用,具体的干货也有,都在图片里,请自行提取 =====18年初原答案 作为一个游戏策划新人,游戏分析可能抓不到点子上,试着总结记录一下游戏体验报告分析的成长(因为水平不同,视野可能也不一样,也许之后几年回头看这些东西都是小儿科或者是错误的,所以只写出当下的想...

eat_human的博客 6万+

华南理工大学电子与信息学院23年预推免复试面试经验贴

华南理工大学电子与信息学院23年预推免复试面试经验贴

Scut_Ty的博客 3295

Spring Boot中@Transactional 注解

Previously: 调用接口先打在Controller上相应方法,然后Controller中调Service再有Service的实现层Impl去实现相应业务,所以ServiceImpl会实现Service的接口一般有注解@Override但是突然发现某个方法下除了@Override居然还有个 @Transactional那这个是个什么东西呢? Spring事务管理分为:编程式和声明式的两种方式 一、编程式事务:指的是通过编码方式实现事务 二、声明式事务:基于 AOP,将业务逻辑与事务处理解耦 声明式事

bnuzxh的博客 979

开关电源EMI滤波设计:如何通过Cx和Cy电容精准抑制共模与差模干扰?

本文深入解析了开关电源EMI滤波设计中Cx和Cy电容的核心作用。Cx电容并联于火线与零线之间,专用于抑制差模干扰;Cy电容连接于火线/零线与地之间,则负责泄放共模干扰。文章详细阐述了二者选型、安规要求及PCB布局要点,并提供了基于测试频谱的实战调优策略,是解决电源传导噪声问题的实用指南。

7z8x2c4v6b9的博客 466

Spring Boot 中 @Transactional 解析

在 Spring Boot 开发中,@Transactional 注解是实现数据库事务管理的关键工具,它能有效确保数据操作的原子性、一致性、隔离性和持久性(ACID)。本文将详细介绍 @Transactional 的使用方法、核心属性、原理以及常见的坑和解决方案。

m0_62923286的博客 857

Spring Boot:如何快速搭建一个高性能微服务架构?

通过本文的详细步骤,我们成功搭建了一个高性能的微服务架构。Spring Boot 和 Spring Cloud 提供了强大的工具链,使得开发者能够快速实现服务注册与发现、负载均衡、熔断器与降级机制等功能。同时,通过数据库连接池、Redis 缓存和异步处理等优化手段,进一步提升了系统的性能和可靠性。希望本文能够帮助你快速入门 Spring Boot 微服务架构的搭建,并为实际项目提供参考。如果你有任何问题或建议,欢迎在评论区留言!

shrgegrb的博客 1013

如何学习总线技术

如何学习总线技术 以形象生动的比喻来描绘了总线技术的基本思想,指出了总线的基本分类和总线传输的基本原理,以及在学习过程中应当掌握的最基本的知识,对初学者有起到抛砖引入的作用。 0引言   如果一座只能容一个人来往的独木桥,两端的人都想要过桥,为了不拥挤、阻塞,那我们就得采取有效的办法。比如规定某段时间哪端的人过桥,另一端的人就等着该他过桥的时间段的到来,同时也还可以规定人多时要按先来后到或年

ce123的技术博客 8527

Spring Boot 的事务注解 @Transactional 失效的几种情况

开发中我们经常会用到 Spring Boot 的事务注解,为含有多种操作的方法添加事务,做到如果某一个环节出错,全部回滚的效果。但是在开发中可能会因为不了解事务机制,而导致我们的方法使用了 `@Transactional` 注解但是没有生效的情况,下面就把这几种不能生效的情况整理一下。

青灯文案的博客 1137

音视频OSD——使用freetype将矢量字库的信息叠加至YUV

目录freetypes使用步骤1)包含头文件:2) 初始化库:3)加载face对象:4)设置字体大小5)设置字体位置,以及旋转度数:6)加载字形图像准备矢量字库代码.c.h效果叠加至YUV freetypes FreeType是一个完全开源的、可扩展、可定制且可移植的字体引擎,它提供TrueType字体驱动的实现统一的接口来访问多种字体格式文件 下载freetypes tar -xjf freetype-2.4.10.tar.bz2 cd freetype-2.4.10/ ./configure

路人coder 2364

使用Spring boot的@Transactional进行事务管理

在 Spring Boot 中,是用于声明式事务管理的关键注解。它基于 Spring 的 AOP(面向切面编程)实现,可以简化数据库事务的管理。

TracyCoder的博客 3399

【人工智能】架构师必读:大模型时代的意图识别 (Intent Recognition) 四大技术流派与实践指南

意图识别没有“银弹”,选择哪种方案取决于具体的业务需求、数据积累以及成本预算。如果追求极简与低成本,BERT 是不二之选。如果业务极其复杂且依赖上下文,RAG 或 Agent 模式更合适。如果追求极致的稳定与效果,基于 LLM 的微调 + Function Calling 是目前的行业最佳实践。参考资源:基于 LLM 的意图识别解决方案(Embedding 相关课程章节)

奶爸的编程之路,也就一周冷个三天 702

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: Java与数据库的时间格式转换
下一篇: 拦截方式之Filter、Interceptor 、Aspect
章 鱼
博客等级 码龄10年 203粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值