栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

@Transactional 失效

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

@Transactional 失效

1,异常被try-catch吃掉

在项目中,@Transactional(rollbackFor=Exception.class),如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚

@Transactional(rollbackFor = Exception.class)
    public void addHazardMater1(HazardMaterQO qo) {
        HazardMater hazardMater = BeanCopyUtil.copyBeanClass(qo, HazardMater.class);
            try{
                hazardMaterMapper.insertSelective(hazardMater);
            }catch (Exception e){
                throw new BusinessException(RequestCodeEnum.MATER_IS_EXIST);
            }
    }

用try-catch 捕捉异之后可以throw一个新的异常,如,throw new RuntimeException(“事务回滚”);
但是这种情况下前端报错,很不友好,所以最好自己定义一个异常类

public class BusinessException extends RuntimeException {

    
    private String code;

    
    private String msg;

    public BusinessException(RequestCodeEnum requestCodeEnum) {
        this.code = requestCodeEnum.getCode();
        this.msg = requestCodeEnum.getMsg();
    }

    public BusinessException(String code,String msg) {
        this.code = code;
        this.msg = msg;
    }

    public BusinessException(String msg) {
        this.msg = msg;
    }

    public String getResponseCode() {
        return code;
    }

    public void setResponseCode(String responseCode) {
        this.code = responseCode;
    }

    @Override
    public String getMessage() {
        return msg;
    }

    public void setMessage(String message) {
        this.msg = message;
    }
}

其中的RequestCodeEnum 是个枚举类,用来存放错误数据的编码

public enum RequestCodeEnum {

    OK("00","成功"),
    ERROR("20","服务器错误"),
    PARAM_ERROR("30","请求参数错误"),

    MATER_IS_EXIST("40", "该数据已重复")
    ;


    private String code;

    private String msg;

    private RequestCodeEnum(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }


    public String getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

或者设置手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackonly();

@Transactional(rollbackFor = Exception.class)
    public void addHazardMater1(HazardMaterQO qo) {
        HazardMater hazardMater = BeanCopyUtil.copyBeanClass(qo, HazardMater.class);
            try{
                hazardMaterMapper.insertSelective(hazardMater);
            }catch (Exception e){
                TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
            }
    }
2、数据库引擎不支持事务

这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。

3、方法不是public

以下来自 Spring 官方文档:

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.
4、自身调用问题: 默认只有在外部调用时候才生效,自身调用没有用

在类内部没有添加@Transactional的方法,调用了@Transactional方法时,当你调用时,他也不会回滚

@Service

public class Testservice{

    public void add(QO qo) {

        addQo(qo);
    }

    @Transactional

    public void addQo(QO qo) {

        // add  Qo
    }

}

失败的原理:@Transactional是基于动态代理对象来实现的,而在类内部的方法的调用是通过this关键字来实现的,没有经过动态代理对象,所以事务回滚失效。

5、没有被Spring管理:service注解被注掉了
//@Service
public class Testservice{
    @Transactional
    public void addQo(QO qo) {
        // add  Qo
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/678615.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号