分析Springboot中嵌套事务失效原因详解

首先两个事务方法,其中一个调用另一个。

@Transactional(rollbackFor = Exception.class)
public void trance() {
    try {
        trance1();//调用下一个事务方法。
    } catch (Exception e) {
        e.printStackTrace();
    }
        User user = new User();
        ShardingIDConfig shardingIDConfig = new ShardingIDConfig();
        user.setId(shardingIDConfig.generateKey().longValue());
        user.setName("trance");
        user.setSex(0);
        userMapper.create(user);
}

@Transactional(propagation = Propagation.REQUIRED)
public void trance1() throws Exception{
    User user = new User();
    ShardingIDConfig shardingIDConfig = new ShardingIDConfig();
    user.setId(shardingIDConfig.generateKey().longValue());
    user.setName("trance1");
    user.setSex(1);
    userMapper.create(user);
    System.out.println(user.getId());
    throw new RuntimeException();
}

添加依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

然后写个测试类,我也是第一次用这个测试

import com.lijia.App;
import com.lijia.service.UserService;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class Test {
    @Autowired
    private UserService userService;

    @org.junit.Test
    public void trance(){
        userService.trance();
    }
}

执行会发现报了RuntimeException,但是数据库里面有两条数据,说明事务失效了

runtimeException

数据库两条数据都上传了,说明事务失效

为什么会出现这种情况呢
spring事务使用了动态代理。还是从动态代理去看。
给出一段代码

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface IHello {
    public void test();
    public void test1();
}
class Hello implements IHello{
    @Override
    public void test() {
        System.out.println("test");
    }

    @Override
    public void test1() {
        System.out.println("test1");
    }
}
public class MyInvoke implements InvocationHandler{
    public Object target;

    public MyInvoke(Object target){
        this.target = target;

    }
     @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().contains("test")){
            System.out.println("========代理了=======");
        }
        return method.invoke(target,args);
    }

    public static void main(String[] args) {
        MyInvoke myInvoke = new MyInvoke(new Hello());
        IHello iHello = (IHello) Proxy.newProxyInstance(MyInvoke.class.getClassLoader(),new Class[]{IHello.class},myInvoke);
        iHello.test();
        iHello.test1();
    }
}

将上面的Hello类中的test1方法放入test方法

    public void test() {
        test1();
        System.out.println("test");
    }

回到上面的问题,会发现trance1()没有走代理,所以会出现两个都插入数据库的操作。
那么需要得到当前的代理对象,然后调用trance1()
通过AopContext.currentProxy()获得当前代理

 ((UserService)AopContext.currentProxy()).trance1();

改成这样调用trance1()
运行Test,然后数据库就剩一条数据了,说明trance1()方法回滚了。

以上就是分析Springboot中嵌套事务失效原因详解的详细内容,更多关于Springboot中嵌套事务失效分析的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解在SpringBoot中@Transactional事物操作和事物无效问题排查

    目录 1.spring事务管理简述 2.SpringBoot中使用@Transactional注解 2.1.开启事务注解 2.2.在目标类.方法上添加注解@Transactional 2.3.细化事务配置 3.@Transactional事务实现机制 3.1.整体事务控制流程 3.2.Spring AOP的两种代理 3.3.事务操作的底层实现 4.@Transactional使用注释实现及问题排查 4.1.数据库引擎是否支持事务? 4.3.注解所在的类是否被加载成Bean? 4.2.注解所在方法

  • Spring事务注解@Transactional失效的八种场景分析

    首先说一下最近自己遇到的一个坑: @Transactional service A(){ try{ insert(); serviceB.update(); }catch(){ throw new RunTimeException(); } } serviceB(){ @Transactional update(){ try{ mapperB.update(); }catch(){ throw new RunTimeException(); } } } mapperB (){ try{ //do

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

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

  • Spring事务失效的几种原因

    数据库引擎不支持事务 在MySQL数据库中有几种引擎(InnoDB,MyISAM,Memory等等),仅仅InnoDB支持事务,如果数据库底层都不支持事务的话,那么再怎么折腾都是白搭. @transactional加在private方法上 @Transactional只能加在public方法上,如果需要在private方法中加入事务,可以使用Aspect配transactionManager使用. 本类方法调本类另一个方法 例如: @Service public class UserServic

  • 分析Springboot中嵌套事务失效原因详解

    首先两个事务方法,其中一个调用另一个. @Transactional(rollbackFor = Exception.class) public void trance() { try { trance1();//调用下一个事务方法. } catch (Exception e) { e.printStackTrace(); } User user = new User(); ShardingIDConfig shardingIDConfig = new ShardingIDConfig(); u

  • SpringBoot中@Autowired生效方式详解

    目录 前言 正文 注册AutowiredProcessor的BeanDefinition 实例化AutowiredProcessor 创建bean时进行注入 后记 前言 @Component public class SimpleBean3 { @Autowired private SimpleBean simpleBean; } @Autowired修饰的字段会被容器自动注入.那么Spring Boot中使如何实现这一功能呢? AutowiredAnnotationBeanPostProces

  • springboot中filter的用法详解

    一.在spring的应用中我们存在两种过滤的用法,一种是拦截器.另外一种当然是过滤器.我们这里介绍过滤器在springboot的用法,在springmvc中的用法基本上一样,只是配置上面有点区别. 二.filter功能,它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.换种说法,filter

  • Springboot中@Value的使用详解

    Springboot通过@Value注解将配置文件中的属性注入到容器内组件中(可用在@Controller.@Service.@Configuration.@Component等Spring托管的类中) 1.普通字符串注入 例:yml中存在key: name: zs @Value注入 @Value("${name}") public String name; 当yml中的name没有对应值时,即yml中为: name: 此时字符串name的值为"" 可设置注入属性的

  • SpringBoot中@ComponentScan的使用详解

    目录 SpringBoot @ComponentScan的使用 SpringBoot @ComponentScan 作用 SpringBoot @ComponentScan的使用 SpringBoot的启动类中有一个@ComponentScan,之前项目由于这个注解造成打包失败,这里对于这个注解进行总结,防止下次遇到这个问题再被难住. 其实这个注解主要是针对于第三方jar包中注解的应用. 如果第三方包中没有使用注解那么就完全不需要使用这个注解 使用方式如图所示,这里扫描的是 maven项目的依赖

  • springboot中thymeleaf模板使用详解

    这篇文章将更加全面详细的介绍thymeleaf的使用.thymeleaf 是新一代的模板引擎,在spring4.0中推荐使用thymeleaf来做前端模版引擎. thymeleaf介绍 简单说, Thymeleaf 是一个跟 Velocity.FreeMarker 类似的模板引擎,它可以完全替代 JSP .相较与其他的模板引擎,它有如下三个极吸引人的特点: 1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页

  • SpringBoot 自动装配的原理详解分析

    目录 前言 自动装配案例 自动装配分析 自动装配总结 前言 关于 ​​SpringBoot​​​ 的自动装配功能,相信是每一个 ​​Java​​ 程序员天天都会用到的一个功能,但是它究竟是如何实现的呢?今天阿粉来带大家看一下. 自动装配案例 首先我们通过一个案例来看一下自动装配的效果,创建一个 ​​SpringBoot​​ 的项目,在 ​​pom​​ 文件中加入下面的依赖. <dependency> <groupId>org.springframework.boot</gro

  • 详解Java中NullPointerException异常的原因详解以及解决方法

    NullPointerException是当您尝试使用指向内存中空位置的引用(null)时发生的异常,就好像它引用了一个对象一样. 当我们声明引用变量(即对象)时,实际上是在创建指向对象的指针.考虑以下代码,您可以在其中声明基本类型的整型变量x: int x; x = 10; 在此示例中,变量x是一个整型变量,Java将为您初始化为0.当您在第二行中将其分配给10时,值10将被写入x指向的内存中. 但是,当您尝试声明引用类型时会发生不同的事情.请使用以下代码: Integer num; num

  • Java 多态中继承的转型详解与用法分析

    目录 一.前言 二.转型 向上转型 向下转型 三.instanceof运算符 instanceof的用处 instanceof的使用格式: 一.前言 前面我们学习了多态的概述和使用,现在我们来学习前面剩下的转型问题. 二.转型

  • MySQL索引失效原因以及SQL查询语句不走索引原因详解

    目录 前言 1. 隐式的类型转换,索引失效 2. 查询条件包含 or,可能导致索引失效 3. like 通配符可能导致索引失效 4. 查询条件不满足联合索引的最左匹配原则 5. 在索引列login_time上使用 mysql 的内置函数 6. 对索引列age进行列运算(如,+.-.*./), 索引不生效 7. 索引字段age上使用(!= 或者 < >, not in),索引可能失效 8. 索引字段上使用 is null, is not null,索引可能失效 (查询结果行数) 9. 左右joi

随机推荐