Transactional 事务回滚遇到的问题 事务传播

本文深入探讨Spring框架下事务管理机制,解析如何正确使用@Transactional注解实现事务回滚,避免常见错误,确保数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单的sql操作---TrancationTest

@Component
public class TrancationTest {

    Logger logger = LoggerFactory.getLogger(TrancationTest.class);

    private UserService userService;

    public TrancationTest(UserService userService){
        this.userService = userService;
    }


    @Transactional(rollbackFor = Exception.class)
    public  void TrancationLog() {
        User user = userService.getUserByUserAccountOrName("sqc");
        logger.info("Transaction 开始执行");
        logger.info("the detail information of user",user);
        try{
            user.setUsername("sqc1");
            userService.updateById(user);
            logger.info("步骤1 the detail information of user",user.toString());
            user.setMail("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            userService.updateById(user);
            logger.info("步骤2 the detail information of user",user.toString());
        }catch (Exception e){
            logger.info("异常");
            throw new RuntimeException();//和下面二选一
//             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
}

测试类------DemoLoginApplicationTests

     @Test
    public void testTranaction() throws Exception {
        TrancationTest trancationTest = new TrancationTest(userService);
        trancationTest.TrancationLog();
    }

TrancationLog中包含着两个操作 一个是简单的修改username不报错 第二个是修改mail邮箱使修改后的邮箱长度超出数据库限制报错   

遇到的问题是:

在外层引用时并没有在测试方法前加Transcation注解  按照事务的传播机制 应该是外部没有事务 运行到trancationTest对象的TrancationLog()方法时 开始新事务 然后走到修改mail报错的部分进行回滚 把之前的修改username的操作一块回滚掉

但是实际并没有 数据库中的username被成功修改了 而且mail的修改因异常中断.

 

 

问了大佬之后,大佬的回答是"spring容器在实例化bean的时候会对每个bean自动生成一个代理类,对加了@Transactional注解的会走代理才会回滚,你自己new的没有对应的代理类"

 

也就是说我自己在 TrancationTest trancationTest = new TrancationTest(userService); 是没有spring管理的实例化过程的,所以也不会有相应的代理类来感知到事务注解 因此才不能回滚.

 

所以只要改成

package com.best800.demologin.service;

import com.best800.demologin.model.DTO.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;


/**
 * @ClassName ${Name}
 * @Description TODO
 * @Author < a href="jcsong50@best-inc.com">sqc</a>
 * @Date 2019/4/8 16:13
 * @Version 1.0
 */
@Component
public class TrancationTest {

    Logger logger = LoggerFactory.getLogger(TrancationTest.class);
    @Autowired
    UserService userService;



    @Transactional(rollbackFor = Exception.class)
    public  void TrancationLog() {
        User user = userService.getUserByUserAccountOrName("sqc");
        logger.info("Transaction 开始执行");
        logger.info("the detail information of user",user);
        try{
            user.setUsername("sqc1");
            userService.updateById(user);
            logger.info("步骤1 the detail information of user",user.toString());
            user.setMail("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            userService.updateById(user);
            logger.info("步骤2 the detail information of user",user.toString());
        }catch (Exception e){
            logger.info("异常");
//            throw new RuntimeException();//和下面二选一
             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

    }


}

 @Autowired
    TrancationTest trancationTest;
    @Test
    public void testTranaction() throws Exception {
        trancationTest.TrancationLog();
    }

轻松搞定.

 

 

还有一个遇到的错误一并写出

@Autowired

static UserService userSerivce;

收获了一波nullPointException   

静态变量、类变量不是对象的属性,而是一个类的属性,所以静态方法是属于类(class)的,普通方法才是属于实体对象(也就是New出来的对象)的,spring注入是在容器中实例化对象,所以不能使用静态方法。

而使用静态变量、类变量扩大了静态方法的使用范围。静态方法在spring是不推荐使用的,依赖注入的主要目的,是让容器去产生一个对象的实例,然后在整个生命周期中使用他们,同时也让testing工作更加容易。

一旦你使用静态方法,就不再需要去产生这个类的实例,这会让testing变得更加困难,同时你也不能为一个给定的类,依靠注入方式去产生多个具有不同的依赖环境的实例,这种static field是隐含共享的,并且是一种global全局状态,spring同样不推荐这样去做。
--------------------- 
作者:_Jason_PC_ 
来源:优快云 
原文:https://blog.youkuaiyun.com/u013675978/article/details/82967202 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值