美文网首页springboot框架原理javaweb收藏
springboot @Transaction注解失效之谜

springboot @Transaction注解失效之谜

作者: 打不开的回忆 | 来源:发表于2018-10-26 14:55 被阅读9次

    使用注解@Transaction声明式事务时,遇到了失效的问题,简要记录,以备后患。

    确保已开启TransactionManagment,让你的注解生效

    • 如果你的项目引入了boot-starter的jbdc或jpa包,则不需要自己配置DataSourceTransactionManager,boot自动配置特性会帮你配置,
    • 如果未正确配置,则需在Application启动类上,使用注解@EnableTransactionManagement让springboot帮你配置
    • 不建议重写config类,自己实现改配置

    确保使用正确的声明式注解@Transactional

    springframework下的注解包类名全称:org.springframework.transaction.annotation.Transactional

    确保注解作用域的方法修饰符

    • @Transaction作用于类上,则该类下的所有public方法生效
    • @Transaction作用于方法上,只有public修饰的方法生效,其余不生效
    • @Transaction最好作用于类/或类的的方法上,而不是接口/或接口的方法上,因为作用于接口上你必须保证使用的是JDK动态代理而不是CGLB代理
      来自springboot官网的解释:

    The Spring team recommends that you annotate only concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces. You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you use interface-based proxies. The fact that Java annotations are not inherited from interfaces means that, if you use class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), the transaction settings are not recognized by the proxying and weaving infrastructure, and the object is not wrapped in a transactional proxy, which would be decidedly bad.

    确保调用的是Aop代理类方法而不是目标方法

    @Transaction注解基于Aop代理生效,所以只有再使用代理类的带有注解的方法才会生效。比如,方法内 调用同类含有@Transaction注解的其他方法,则执行的是目标类方法(本类方法),而不是代理类的方法,所以不会生效

    确保@Transaction的回滚异常

    • 手动try/catch吃掉异常,显然不会回滚
    • 未正确声明回滚/不回滚的异常类型,注解默认回滚RuntimeException和Error,其他查询异常不会回滚,可以使用@Transaction的rollbackFor和noRollbackFor属性设置异常类型

    确保数据库表引擎支持事务

    使用JPA的spring.jpa.hibernate.ddl-auto配置自动创建的表,默认引擎是engine=MyISAM,是不支持事务的,使用JPA要注意这点,建议不要打开自动创建表配置。
    查看/修改数据库表引擎的命令:

    show create TABLE customer;
    
    CREATE TABLE `customer` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `address` varchar(255) DEFAULT NULL,
      `email` varchar(255) DEFAULT NULL,
      `name` varchar(255) DEFAULT NULL,
      `phone` varchar(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=38 DEFAULT CHARSET=utf8
    
    ALTER TABLE customer ENGINE = INNODB;
    

    以上就是常遇到的几个问题,后续开发在遇到类似问题,持续更新!
    文章如有不正之处请联系作者进行修改,万分感谢!
    微信:


    weixin

    相关文章

      网友评论

        本文标题:springboot @Transaction注解失效之谜

        本文链接:https://www.haomeiwen.com/subject/uawktqtx.html