当前位置: 代码网 > it编程>编程语言>Java > Springboot中@Transactional注解与异常处理机制方式

Springboot中@Transactional注解与异常处理机制方式

2024年08月06日 Java 我要评论
springboot @transactional注解与异常处理机制@transactional注解的方法默认会捕获所有非检查异常,即runtimeexception和error,可以通过括号声明显示

springboot @transactional注解与异常处理机制

@transactional注解的方法默认会捕获所有非检查异常,即runtimeexception和error,可以通过括号声明显示指定处理异常类,如exception.class

关于异常处理机制:

当代码抛出异常时,异常处理的优先级如下:

  • try-catch 块:如果在代码中使用了 try-catch 块来捕获异常,异常将会首先被 try-catch 块捕获并处理。只有在 try-catch 块中未处理(重新抛出)异常时,异常才会继续传播。
  • @transactional:如果异常从 try-catch 块中传播出来,spring 的事务管理器(由 @transactional 注解管理)会捕获异常并决定是否回滚事务。事务处理之后,异常继续传播。
  • @exceptionhandler:最后,异常会被全局异常处理器(由 @controlleradvice 和 @exceptionhandler 注解管理)捕获并处理。

因此,对于手动捕获的异常,需要手动将其抛出才会被@transactional处理器捕获,全局处理器的优先级最后,除了特殊的异常可能需要调整传播顺序,大部分不需要考虑其影响。

@transactional错误集锦以及如何正确使用

原理

@transactional 是声明式事务管理 编程中使用的注解,通过spring aop在注解修饰方法的前后织入事务管理的实现语句,所以开发者只需要通过一个注解就能代替一系列繁琐的事务开始、事务关闭等重复性的编码任务。

添加位置

  • 接口实现类或接口实现方法上,而不是接口类中。
  • 访问权限:public 的方法才起作用。@transactional 注解应该只被应用到 public 方法上,这是由 spring aop 的本质决定的。
  • 系统设计:将标签放置在需要进行事务管理的方法上,而不是放在所有接口实现类上:只读的接口就不需要事务管理,由于配置了@transactional就需要aop拦截及事务的处理,可能影响系统性能。

错误案例

1.同一个类中调用

public class a {
    
    public void methoda() {
        methodb();
        
        // 其他操作
    }

    @transactional
    public void methodb() {
        // 写数据库操作
    }
    
}

上面案例是错误的基于spring aop的拦截机制,将会忽略事务。

解决方式如下:

@service@allargsconstructorpublic class a {        private b b;        public void methoda() {        b.methodb();        // 其他操作    }}@servicepublic class b {
    @transactional    public void methodb() {        // 写数据库操作    }    }

注意:这里的b类没有用@autowrire,构造函数用lombok的@allargsconstructor生成 自动注入了。

2. @transactional修饰方法不是public

public class transactionalmistake {
    
    @transactional
    private void method() {
        // 写数据库操作
    }
    
}

这也是基于spring aop实现的注解所要满足的要求。这个最简单, 直接把方法访问类型改成public即可。

3. 不同的数据源

public class transactionalmistake {

    @transactional
    public void createorder(order order) {
        orderrepo1.save(order);
        orderrepo2.save(order);
    }

}

上面这个例子里的orderrepo1和orderrepo2是连接的两个不同数据源。

默认情况下,这种跨数据源的事务是不会成功的。

如果要在多个数据源之间实现事务,那么可以引入jta。

4. 回滚异常配置不正确

默认情况下,仅对runtimeexception和error进行回滚。

如果不是的它们及它们的子孙异常的话,就不会回滚。

如果不是runtimeexception,但也希望触发回滚,那么可以使用rollbackfor属性来指定要回滚的异常。

public class transactionalmistake {

    @transactional(rollbackfor = xxxexception.class)
    public void method() throws xxxexception {

    }

}

5. 数据库引擎不支持事务

spring.jpa.database-platform=org.hibernate.dialect.mysql5innodbdialect

这里的spring.jpa.database-platform配置主要用来设置hibernate使用的方言。

这里特地采用了mysql5innodbdialect,主要为了保障在使用spring data jpa时候,hibernate自动创建表的时候使用innodb存储引擎,不然就会以默认存储引擎myisam来建表,而myisam存储引擎是没有事务的。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com