Spring如何在一个事务中开启另一个事务

这篇文章主要介绍了Spring如何在一个事务中开启另一个事务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

spring使用@Transactional开启事务,而且该注解使用propagation属性来指定事务的传播级别

@Transactional(propagation =Propagation.REQUIRES_NEW) // 开启一个新事务

使用REQUIRES_NEW就会开启一个新的事务吗? 答案并不是.

请看下面的这个示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import qinfeng.zheng.learnpagequery.domain.UserDO;
import qinfeng.zheng.learnpagequery.mapper.UserMapper;

@Service
public class UserService {
  @Autowired
  private UserMapper userMapper;

  @Transactional(rollbackFor = Exception.class)
  public void doSomething(UserDO userDo) {
    insert(userDo);
    doOther();
  }

  @Transactional(propagation =Propagation.REQUIRES_NEW) // 开启一个新事务
  public void insert(UserDO userDo) {
    userMapper.insert(userDo);
  }

  public void doOther() {
    System.out.println("做一些其它的事,比如调用其它的系统");
  }
}

在调用doSomething方法时,开启了一个事务,该方法中包括insert和doOther, 但是insert方法上也开启了一个事务. 按道理应该有两个事务控制,可事实上并不是, insert方法的事务无效. 这就跟spring事务原理有关系, spring框架是通过TransactionInterceptor类来控制事务开启,提交,回滚等, 它会创建一个目标类的代理类. 而在本示例中,doSomething方法调用insert方法时,并不是通过代理类去调用,而是通过this调用本身的方法insert方法.所以insert方法的事务并不会开启.

解决方法

1. 将insert方法抽取到另一个XxxService方法中, 然后再将这个XxxService注入到UserService类中,通过xxxService.insert()调用, 这样insert方法的事务就会生效了.

2. 第2种方式通过AopContext创建一个代理

 在项目启动类上开启 exposeProxy = true

@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@Transactional(rollbackFor = Exception.class)
public void doSomething(UserDO userDo) {
  UserService userService = (UserService) AopContext.currentProxy();
  userService.insert(userDo); // 这样insert方法事务生效
  doOther();
}

备注: 在springboot1.x中使用@EnableTransactionManagement开启事务, 但是在springboot2.x中,默认就开启了事务,所以勿须在启动类上添加此注解了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • springboot中事务管理@Transactional的注意事项与使用场景

    前言:在service层的方法上使用@Transactional 即可实现处理数据库发生错误时触发事务回滚机制. 注意: Spring 基于注解的声明式事物 @Transactional 默认情况下只会对运行期异常(java.lang.RuntimeException及其子类)和 Error 进行回滚. 数据库引擎要支持事物,使用InnoDB. @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没

  • 详解Spring Boot微服务如何集成fescar解决分布式事务问题

    什么是fescar? 关于fescar的详细介绍,请参阅fescar wiki. 传统的2PC提交协议,会持有一个全局性的锁,所有局部事务预提交成功后一起提交,或有一个局部事务预提交失败后一起回滚,最后释放全局锁.锁持有的时间较长,会对并发造成较大的影响,死锁的风险也较高. fescar的创新之处在于,每个局部事务执行完立即提交,释放本地锁:它会去解析你代码中的sql,从数据库中获得事务提交前的事务资源即数据,存放到undo_log中,全局事务协调器在回滚的时候直接使用undo_log中的数据覆

  • Spring中使用atomikos+druid实现经典分布式事务的方法

    经典分布式事务,是相对互联网中的柔性分布式事务而言,其特性为ACID原则,包括原子性(Atomictiy).一致性(Consistency).隔离性(Isolation).持久性(Durabilit): 原子性:事务是一个包含一系列操作的原子操作.事务的原子性确保这些操作全部完成或者全部失败. 一致性:一旦事务的所有操作结束,事务就被提交.然后你的数据和资源将处于遵循业务规则的一直状态. 隔离性:因为同时在相同数据集上可能有许多事务处理,每个事务应该与其他事务隔离,避免数据破坏. 持久性:一旦事

  • spring整合atomikos实现分布式事务的方法示例

    前言 Atomikos 是一个为Java平台提供增值服务的并且开源类事务管理器,主要用于处理跨数据库事务,比如某个指令在A库和B库都有写操作,业务上要求A库和B库的写操作要具有原子性,这时候就可以用到atomikos.笔者这里整合了一个spring和atomikos的demo,并且通过案例演示说明atomikos的作用. 准备工作 开发工具:idea 数据库:mysql , oracle 正文 源码地址: https://github.com/qw870602/atomikos 演示原理:通过在

  • Spring中事务管理的四种方法(银行转账为例)

    前言 本文配套示例代码下载地址(完整可运行,含sql文件,下载后请修改数据库配置):点击这里下载 一.事务的作用 将若干的数据库操作作为一个整体控制,一起成功或一起失败. 原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生. 一致性:指事务前后数据的完整性必须保持一致. 隔离性:指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离. 持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即时数据库发生故障也不应

  • SpringBoot+Dubbo+Seata分布式事务实战详解

    前言 Seata 是 阿里巴巴开源的分布式事务中间件,以高效并且对业务0侵入的方式,解决微服务场景下面临的分布式事务问题. 事实上,官方在GitHub已经给出了多种环境下的Seata应用示例项目,地址:https://github.com/seata/seata-samples. 为什么笔者要重新写一遍呢,主要原因有两点: 官网代码示例中,依赖太多,分不清哪些有什么作用 Seata相关资料较少,笔者在搭建的过程中,遇到了一些坑,记录一下 一.环境准备 本文涉及软件环境如下: SpringBoot

  • SpringBoot内部调用事务不起作用问题的解决方案

    在做业务开发时,遇到了一个事务不起作用的问题.大概流程是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚.查阅资料后,问题得到解决,记录下来分享给大家. 场景 我在这里模拟一个场景,大概的调用方式就如下面的代码这样. @Override @Transactional(rollbackFor = RuntimeException.class) public void insertUser(User user) { userMapper.insertUser(user); thr

  • SpringDataMongoDB多文档事务的实现

    一.安装MongoDB4.0.3(××) 1.1.官方安装文档 https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/ 1.2.tar.gz包下载地址 https://www.mongodb.com/download-center/community?jmp=docs 1.3.复制集官方配置 https://docs.mongodb.com/manual/administration/replica-set-mem

  • Spring编程式和声明式事务实例讲解小结

    Spring事务管理 Spring支持两种方式的事务管理: 编程式事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用, 使用XML配置声明式事务: 推荐使用(代码侵入性最小),实际是通过AOP实现 实现声明式事务的四种方式: 基于 TransactionInterceptor 的声明式事务: Spring 声明式事务的基础,通常也不建议使用这种方式,但是与前面一样,了解这种方式对理解 Spring 声明式事务有很大作用. 基于 TransactionProx

  • Spring如何在一个事务中开启另一个事务

    这篇文章主要介绍了Spring如何在一个事务中开启另一个事务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 spring使用@Transactional开启事务,而且该注解使用propagation属性来指定事务的传播级别 @Transactional(propagation =Propagation.REQUIRES_NEW) // 开启一个新事务 使用REQUIRES_NEW就会开启一个新的事务吗? 答案并不是. 请看下面的这个示例 imp

  • SQLServer数据库中开启CDC导致事务日志空间被占满的原因

    SQLServer中开启CDC之后,在某些情况下会导致事务日志空间被占满的现象为: 在执行增删改语句(产生事务日志)的过程中提示,The transaction log for database '***' is full due to 'REPLICATION'(数据库"***"的事务日志已满,原因为"REPLICATION"). CDC以及复制的基本原理粗略地讲,对于日志的使用步骤如下: 1,每当基础表(开启了CDC或者replication的表)产生事务性操作

  • Android编程实现在一个程序中启动另一个程序的方法

    本文实例讲述了Android编程实现在一个程序中启动另一个程序的方法.分享给大家供大家参考,具体如下: Android 开发有时需要在一个应用中启动另一个应用,比如Launcher加载所有的已安装的程序的列表,当点击图标时可以启动另一个应用. 一般我们知道了另一个应用的包名和MainActivity的名字之后便可以直接通过如下代码来启动: Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEG

  • Java中实现在一个方法中调用另一个方法

    在同一个类中: 对于静态方法,其他的静态或非静态方法都可以直接调用它. 而对于非静态方法,其他的非静态方法是可以直接调用它的.但是其他静态方法只有通过对象才能调用它. 静态方法不能被非静态方法覆盖. public class Test2 { public static void s1(){ System.out.println("s1"); } public void say1(){ System.out.println("say1"); } public void

  • oracle 在一个存储过程中调用另一个返回游标的存储过程

    第一种情况是返回的游标是某个具体的表或视图的数据,如: SQL-Code: 复制代码 代码如下: CREATE OR REPLACE PROCEDURE P_TESTA ( PRESULT OUT SYS_REFCURSOR ) AS BEGIN OPEN PRESULT FOR SELECT * FROM USERS; END P_TESTA; 其中USERS就是数据库中一个表.在调用的时候只要声明一个该表的ROWTYPE类型就可以了: SQL-Code: 复制代码 代码如下: CREATE

  • SQL Server误区30日谈 第26天 SQL Server中存在真正的“事务嵌套”

    误区 #26: SQL Server中存在真正的"事务嵌套"错误 嵌套事务可不会像其语法表现的那样看起来允许事务嵌套.我真不知道为什么有人会这样写代码,我唯一能够想到的就是某个哥们对SQL Server社区嗤之以鼻然后写了这样的代码说:"玩玩你们".    让我更详细的解释一下,SQL Server允许你在一个事务中开启嵌套另一个事务,SQL Server允许你提交这个嵌套事务,也允许你回滚这个事务.    但是,嵌套事务并不是真正的"嵌套",对

  • Angular在一个页面中使用两个ng-app的方法(二)

    在上篇文章给大家介绍了Angular在一个页面中使用两个ng-app的方法,这种方法不太推荐,下面给大家介绍方法二,具体代码如下所示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>ng-app指令,angular找到第一个ng-app就不会再找了,在一个页面中只使用一个ng-app.</title>

  • Angular在一个页面中使用两个ng-app的方法

    下面一段代码给大家介绍了Angular在一个页面中使用两个ng-app的方法,具体代码如下所示: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>ng-app指令,angular找到第一个ng-app就不会再找了,在一个页面中只使用一个ng-app.</title> </head> <b

  • Spring事务的开启原理详解

    在事务配置类上声明@EnableTransactionManagement注解开启事务 在事务配置类上定义数据源 在事务配置类上定义事务管理器 在相关类或者方法上使用@Transactional声明事务 代码如下: @Configuration @EnableTransactionManagement public class RootConfig{ @Bean public DataSource dataSource(){ DruidDataSource dataSource = new Dr

  • python 已知一个字符,在一个list中找出近似值或相似值实现模糊匹配

    已知一个元素,在一个list中找出相似的元素 使用场景: 已知一个其它来源的字符串, 它有可能是不完全与我数据库中相应的字符串匹配的,因此,我需要将其转为适合我数据库中的字符串 使用场景太绕了, 直接举例来说吧 随便举例: 按青岛城市的城区来说, 我数据库中存储的城区是个list:['市北区', '市南区', '莱州市', '四方区']等 从其它的数据来源得到一个城区是:市北 我怎么得到与市北相似相近的市北区 解决方案: In [1]: import difflib In [2]: cityar

随机推荐