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日

相关文章

  • 浅谈Java实体对象的三种状态以及转换关系

    浅谈Java实体对象的三种状态以及转换关系 在Java中,实体对象主要存在3种状态:瞬时状态、持久状态和游离状态。实体对象的状态会影响到实体对象在数据库中的存储及更新,因此在实际应用中应特别注意。 1. 瞬时状态 当Java程序中创建一个新对象时,该实体对象处于瞬时状态。瞬时状态的实体对象不与数据库中的任何数据对应,因此它也不具有持久化的能力。也就是指,我们…

    Java 2023年5月20日
    00
  • JavaMail与Spring整合过程解析

    下面我将详细讲解“JavaMail与Spring整合过程解析”的完整攻略。 一、前言 JavaMail是用来发送和接收邮件的一个API,而Spring是Java的一个轻量级框架,提供了众多开发中需要的功能。JavaMail和Spring的整合可以让我们更加方便地使用JavaMail来处理邮件相关的业务逻辑。接下来,我将详细讲解JavaMail与Spring整…

    Java 2023年5月31日
    00
  • JSP教程(一)

    下面是“JSP教程(一)”的完整攻略: JSP教程(一) 什么是JSP JSP(Java Server Pages) 是一种动态网页开发技术,它是由Servlet API的编程模型衍生而来的。JSP技术将Java代码嵌入到HTML文档中,用于动态处理网页的内容。当客户端发起请求时,JSP容器会将JSP编译为Servlet并执行。 JSP的特点 处理动态内容 …

    Java 2023年6月15日
    00
  • springboot 使用Spring Boot Actuator监控应用小结

    下面是对“springboot使用SpringBootActuator监控应用小结”的详细讲解,包含完整的攻略和示例。 1. 什么是SpringBootActuator SpringBootActuator是SpringBoot框架下的一个辅助工具,可以帮助开发者更好的管理和监控应用程序的运行情况。通过向应用程序的运行时环境中添加各种监控指标,开发者可以实时…

    Java 2023年5月15日
    00
  • Spring Security权限管理实现接口动态权限控制

    以下是关于Spring Security权限管理实现接口动态权限控制的完整攻略: 1. 什么是接口动态权限控制 接口动态权限控制即根据用户的权限动态的对接口进行权限控制,这个过程可以分为两步:一是获取用户所拥有的权限,二是根据用户所拥有的权限动态的对接口进行控制。 2. Spring Security实现接口动态权限控制的步骤 以下是实现Spring Sec…

    Java 2023年6月3日
    00
  • 实例化JFileChooser对象报空指针异常问题的解决办法

    当实例化JFileChooser对象时,很有可能会遇到空指针异常问题。这可能是由于操作系统的文件选择器出现问题导致的,也可能是由于缺少必要的UI组件,导致无法正确实例化对象。在这里我们提供两种解决办法,以帮助您解决这个问题。 解决办法1:添加必要的UI组件 如果您遇到了实例化JFileChooser对象时出现“空指针异常”的问题,很有可能是因为缺少必要的UI…

    Java 2023年5月27日
    00
  • 微信小程序以ssm做后台开发的实现示例

    下面我将详细讲解如何使用ssm框架进行微信小程序后台开发的实现示例。 一、什么是SSM框架 SSM框架实际上是Spring、SpringMVC和MyBatis三个框架的结合,可以高效稳定地进行Java Web开发。其中,Spring是用于控制Bean的,SpringMVC是用于控制请求的,MyBatis是用于控制数据的。部署方便,使用简单,很适合中小型互联网…

    Java 2023年5月23日
    00
  • Java字符串去除特殊字符内容的实例

    下面是Java字符串去除特殊字符内容的实例的完整攻略。 1. 确定需要去除的特殊字符 在进行字符串的特殊字符去除操作之前,需要先确定需要去除的特殊字符。常见的特殊字符有空格、制表符、换行符等。可以使用Java字符串的正则表达式进行匹配。 2. 使用replaceAll方法进行特殊字符去除 Java的字符串类中提供了replaceAll方法,可以使用正则表达式…

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