spring事务传播的Propagation.REQUIRES_NEW以及NEVER MANDATORY验证,及其失效的诡异问题

NEVER

不使用事务,如果当前事务存在,则抛出异常

验证:

@Service
public class PrService {
    @Autowired
    PrDao dao;   
    @Transactional
    public void savea() {
        dao.a();//保存第一条数据
        saveb();
    }
    @Transactional(propagation = Propagation.NEVER)
    private void saveb() {
        dao.b();//保存第二条数据
        int i=1/0;
    }
}

写一个controller调用这个savea方法,页面看到的是/ by zero,数据库中两条数据都没有插入进去,都回滚了。照说设置了Propagation.NEVER,应该saveb方法根本执行不了,报never的错。为什么执行了呢?

因为是直接调用的saveb(),不是从代理对象上调用的方法,改成这样:

@Service
public class PrService {
    @Autowired
    PrDao dao;
    
    @Autowired
    PrService prService;
    
    @Transactional
    public void savea() {
        dao.a();//保存第一条数据
        prService.saveb();
    }

    @Transactional(propagation = Propagation.NEVER)
    private void saveb() {
        dao.b();//保存第二条数据
        int i=1/0;
    }
}

注意这里是  prService.saveb()和前面不同,但是居然在  dao.b(); 这一行报了一个空指针的错误,这就诡异了,这个dao明明在上面的savea方法里面还有值的,你知道是为什么吗?

原来saveb方法的修饰符是private,导致代理对象无法继承这个方法。改成public

public void saveb()

再次测试,看到期待的报错了:

Existing transaction found for transaction marked with propagation 'never'

 

 

MANDATORY

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

这里把MANDATORY放在saveb方法上,就要把savea方法上的transactional注解去掉,才能看到报错。

@Service
public class PrService {
    @Autowired
    PrDao dao;
    
    @Autowired
    PrService prService;

    public void savea() {
        dao.a();//保存第一条数据
        prService.saveb();
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void saveb() {
        dao.b();//保存第二条数据
    }
}

或者直接把MANDATORY放在a方法上也会报错:

@Service
public class PrService {
    @Transactional(propagation = Propagation.MANDATORY)
    public void savea() {
    }
}

报错如下

No existing transaction found for transaction marked with propagation 'mandatory'

 

REQUIRES_NEW

创建一个新事务,如果存在当前事务,则挂起该事务。

可以理解为设置事务传播类型为REQUIRES_NEW的方法,在执行时,不论当前是否存在事务,总是会新建一个事务。

现在写一个demo验证,savea方法调用saveb方法,希望saveb方法里面异常了且事务回滚,savea方法里面不回滚

下面验证:

同样为了在避免事务失效,在代理对象上调用方法,将被调用的方法放到一个单独的类中:

@Service
public class PrService {
    @Autowired
    PrDao dao;

    @Autowired
    SaveBService saveBService;

    @Transactional
    public void savea() {
        dao.a();//插入第一条数据
        saveBService.saveb();
    }
}
@Service
public class SaveBService {
    @Autowired
    PrDao dao;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveb() {
        dao.b();//插入第二条数据
        int i = 1/0;
    }
}

这里PrService的savea方法调用SaveBService的saveb方法,写一个controller访问savea方法,页面看到一个异常 / by zero,再检查数据库,两条数据都有没有插入进去。这是为什么呢?看上去第二个方法已经写到独立的类中了。

原来是因为saveb方法抛出的异常savea方法没有捕获,又抛出去了,当然要回滚了。写个try catch就行:

    @Transactional
    public void savea() {
        dao.a();//插入第一条数据
        try {
            saveBService.saveb();
        }catch (Exception e) {
            System.out.println("some error");
        }
    }

再次测试,第二条数据没有插入,第一条数据插入到数据库了,页面也看不到报错了。

 

原文链接:https://www.cnblogs.com/gong2021/p/17382817.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring事务传播的Propagation.REQUIRES_NEW以及NEVER MANDATORY验证,及其失效的诡异问题 - Python技术站

(0)
上一篇 2023年5月8日
下一篇 2023年5月8日

相关文章

  • 你应该知道的这些Mybatis-Plus使用技巧(小结)

    你应该知道的这些Mybatis-Plus使用技巧(小结) Mybatis-Plus是一个Mybatis的增强工具,拓展了Mybatis的功能,使得开发者在编写数据库CRUD操作时更加方便和快捷。本文将介绍一些Mybatis-Plus的使用技巧。 1. 自动生成代码 Mybatis-Plus提供了一种快速生成Mapper、实体类、Service、Service…

    Java 2023年5月20日
    00
  • Java泛型T,E,K,V,N,?与Object区别和含义

    Java泛型是Java 5之后引入的新特性,可以让我们编写更加类型安全的代码。在泛型中,T、E、K、V、N 和 ? 是常见的符号。它们代表的是不同的类型参数。 T T 是 Java 泛型中最常见的类型,表示任意类型。在定义类或方法时,我们可以使用 T 代替所有可能的类型。例如,下面是一个定义了一个泛型类的例子: public class Box<T&g…

    Java 2023年5月26日
    00
  • Java 中EasyExcel的使用方式

    下面是Java中EasyExcel的使用方式的完整攻略: 1. 简介 EasyExcel是一款基于Java开发的、功能强大的Excel读写解决方案,使用起来方便快捷,支持读写Excel、CSV、HTML、JSON等文件格式,并且具有高性能,内存消耗低等优点,是目前比较流行的Excel读写工具之一。 2. 如何使用 2.1 引入依赖 在项目中引入EasyExc…

    Java 2023年6月2日
    00
  • springboot 按月分表的实现方式

    下面是springboot按月分表的实现方式完整攻略: 第一步:创建表和初始化数据 首先,我们需要创建一张原始的订单表,结构如下: CREATE TABLE `order` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘主键ID’, `order_no` varchar(64) DEFAULT NULL…

    Java 2023年5月20日
    00
  • Java之SpringBoot实现基本增删改查(前后端分离版)

    Java之SpringBoot实现基本增删改查(前后端分离版)攻略 简介 本篇攻略主要介绍如何使用SpringBoot实现前后端分离模式下的基本增删改查操作。在本文中,我们将使用MySQL数据库和Vue.js作为前端技术栈。此外,后端所使用的工具主要有SpringBoot、MyBatis和Swagger。在完成本文所述内容之前,请确保你已完成以下几个环节: …

    Java 2023年5月15日
    00
  • Java实现经典拳皇误闯冒险岛游戏的示例代码

    让我来详细给你讲解Java实现经典拳皇误闯冒险岛游戏的示例代码的完整攻略。 核心思路 经典拳皇误闯冒险岛游戏的核心思路是将两个游戏融合在一起,使得玩家能够在游戏中既能享受打拳皇的快感,又能够领略冒险岛的神奇之旅。在实现这个目标的过程中,需要分别实现拳皇游戏和冒险岛游戏的核心逻辑,并将它们合并在一起。 实现步骤 首先,我们需要将拳皇游戏的代码和冒险岛游戏的代码…

    Java 2023年5月23日
    00
  • 【SSM】一、了解Sping 框架

    〇、Maven 0.1 什么是Maven? Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build…

    Java 2023年4月25日
    00
  • Java中JavaBean对象和Map的互相转换方法实例

    JavaBean对象和Map之间的转换是Java中常见的操作。在处理数据时,我们可以将JavaBean转换为Map方便地获取属性值,也可以将Map转换为JavaBean以便于进行数据处理。接下来,我将为您提供一份JavaBean对象和Map的互相转换方法示例攻略。 JavaBean对象转换为Map 将JavaBean对象转换为Map可以使用Java中的反射技…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部