文章目录

  • Pre
  • What
  • How
    • 方法一 编程式事务
    • 使用@Transactional 又能避免产生长事务
      • 方法一
      • 方法二


Pre

SpringBoot - 实践阿里巴巴【Manager 层_通用业务处理层】

在Spring体系中,在方法上加上注解@Transactional,Spring自动帮我们进行事务的开启、提交、回滚操作,真的是太方便了,以至于不分青红皂白,啥都搞上…


What

运行时间比较长,长时间未提交的事务,都可以称之为长事务

长事务引发的常见危害有:

  • 数据库连接池被占满,应用无法获取连接资源
  • 容易引发数据库死锁
  • 数据库回滚时间长
  • 在主从架构中会导致主从延时变大 等等

How

原则: 对事务方法进行拆分,尽量让事务变小,变快,减小事务的颗粒度

我们知道@Transactional注解进行事务管理的操作叫声明式事务, 使用声明式事务的优点 很明显,简单,仅需要关注业务, Spring框架自动帮我们进行事务的开启、提交以及回滚等操作。

声明式事务有一个最大的缺点,就是事务的颗粒度是整个方法,无法进行精细化控制。

那 与声明式事务对应的就是编程式事务 是不是可以解决 颗粒度的问题呢?

方法一 编程式事务

基于底层的API,开发者在代码中手动的管理事务的开启、提交、回滚等操作。

在spring项目中我们可以使用TransactionTemplate类的对象,手动控制事务。

@Autowired
private TransactionTemplate transactionTemplate; ... public void save(ArtisanDto artisanDto) { transactionTemplate.execute(transactionStatus -> {artisanDao.save(artisanDto);//....// .....return Boolean.TRUE; });
}

使用编程式事务最大的好处就是可以精细化控制事务范围, 所以避免长事务最简单的方法就是不要使用声明式事务@Transactional,而是使用编程式事务手动控制事务范围。

使用@Transactional 又能避免产生长事务

那既想使用@Transactional 又想避免产生长事务呢?

那就需要对方法进行拆分,将不需要事务管理的逻辑与事务操作分开.

@Service
public class ArtisanService{public void create(ArtisanDto dto){queryData();biz();save(dto);}//事务操作@Transactional(rollbackFor = Throwable.class)public void save(ArtisanDto  dto){artisanDao.insert(dto);}
}

queryData()与biz()不需要事务,我们将其与事务方法save()拆开.

这种拆分会命中使用@Transactional注解时事务不生效的经典场景. @Transactional注解的声明式事务是通过spring aop起作用的,而spring aop需要生成代理对象,直接在同一个类中方法调用使用的还是原始对象,事务不生效。

其他几个常见的事务不生效的场景为:

  • @Transactional 应用在非 public 修饰的方法上
  • @Transactional 注解属性 propagation 设置错误
  • @Transactional 注解属性 rollbackFor 设置错误
  • 同一个类中方法调用,导致@Transactional失效
  • 异常被catch捕获导致@Transactional失效

每日一博 - 常见的Spring事务失效&事务不回滚案例集锦

所以正确的拆分方法应该是下面两种

方法一

可以将方法放入另一个类,如新增 manager层,通过spring注入,这样符合了在对象之间调用的条件。

@Service
public class ArtisanService{@Autowiredprivate ArtisanManager artisanManager;public void create(ArtisanDto dto){queryData();biz();artisanManager.save(dto);}
}
@Service
public class ArtisanManager{@Autowiredprivate ArtisanDao artisanDao;@Transactional(rollbackFor = Throwable.class)public void save(ArtisanCreateDTO dto){artisanDao.saveData(dto);}
}

参考 SpringBoot - 实践阿里巴巴【Manager 层_通用业务处理层】

方法二

启动类添加@EnableAspectJAutoProxy(exposeProxy = true),方法内使用AopContext.currentProxy()获得代理类,使用事务。

@EnableAspectJAutoProxy(exposeProxy = true)
@SpringBootApplication
public class SpringBootApplication {}
public void createArtisan(ArtisanCreateDTO dto){ArtisanService artisanService = (ArtisanService)AopContext.currentProxy();artisanService.saveData(dto);
}


SpringBoot - 优雅的处理【长事务】相关推荐

  1. SpringBoot优雅编码之:Lombok加持

    概述 Lombok 通过提供简单的语法注解形式来帮助简化消除一些必须有但显得很臃肿的 java 代码.典型的是对于 POJO对象的简化(如自动帮我们生成Setter和Getter等),有了Lombok ...

  2. SpringBoot优雅整合RocketMQ

    SpringBoot优雅整合RocketMQ 本篇文章默认你已经有RocketMQ的基础: Producer启动过程,消息发送过程 Consumer启动过程,消息拉取消息消费过程 NameServer ...

  3. SpringBoot 优雅停机

    目录 linux常用的 kill 指令 springboot 优雅停机 /actuator/shutdown 端点 不停机更新方案 linux常用的 kill 指令 kill -15:kill指令默认 ...

  4. 增加自增列 耗时长_又一批长事务,P0故障谁来背锅?

    原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. 最近几周,发生过多起因为事务问题引起的服务报错.现象为数据库连接池连接占满,数据库连接长时间等待,最终导致请求线程hang ...

  5. SpringBoot - 优雅的实现【业务校验】高级进阶

    文章目录 Pre 需求 实现三部曲 实体类 Step1 搞两个自定义注解 Step2 搞自定义校验器 Step3 搞验证 小结 源码 Pre SpringBoot - 优雅的实现[参数校验]高级进阶 ...

  6. SpringBoot - 优雅的实现【参数分组校验】高级进阶

    文章目录 Pre 需求 实现三部曲 Step1 定义分组接口 Step2 给参数分配分组 Step3 指定分组 Step4 验证 源码 Pre SpringBoot - 优雅的实现[参数校验]高级进阶 ...

  7. SpringBoot - 优雅的实现【自定义参数校验】高级进阶

    文章目录 Pre 概述 三部曲 Step1 搞自定义注解 Step2 搞校验逻辑 Step3 使用 Step4 验证 附 int 类型的判断 源码 Pre SpringBoot - 优雅的实现[参数校 ...

  8. SpringBoot - 优雅的实现【参数校验】高级进阶

    文章目录 Pre 概述 参数校验三部曲 Step1 搞依赖 Step2 搞参数校验的实体类 常用的校验注解 Step3 开始验证 存在的问题 使用 统一格式 + 全局异常Handler 优化 源码 P ...

  9. 为什么不要使用长事务

    比如,在某个时刻(今天上午9:00)开启了一个事务A(对于可重复读隔离级别,此时一个视图read-view A也创建了),这是一个很长的事务-- 事务A在今天上午9:20的时候,查询了一个记录R1的一 ...

最新文章

  1. ggplot2中显示坐标轴_R可视化11|ggplot2-图层图形语法 (3)
  2. 使用 Eclipse PhoneGap 构建 Android
  3. Oracle数据库的impdp导入操作以及dba_directories使用方法
  4. 技术面试的时候应该了解公司点什么
  5. 【2016 Asia China-Final D题】
  6. 深度学习核心技术精讲100篇(十四)-一文带你看懂GPflow的前世今生
  7. MVP on Android
  8. 科普 | CPU 是如何工作的?
  9. php实现金币提现,PHP实现微信提现功能
  10. 昇兴集团:搭建帆软报表系统,打破数据孤岛,工作效率提升5倍
  11. centos7.5 部署flask+nginx+uwsgi+python3
  12. 云原生2.0时代下,DevOps实践如何才能更加高效敏捷?
  13. Hdu2680 最短路
  14. 撰写oracle-sql-hint的注意事项
  15. java后端开发项目流程_Java项目——后端笔记
  16. java jsch执行脚本_JSch远程执行脚本
  17. 单词发音网页 (文本处理 python)
  18. 图片合成雾的方法概述
  19. Reds关键技术分析及应用
  20. 素数的平方阶群必为Abel群

热门文章

  1. java中队列链表栈的作用_Java用链表实现栈和队列
  2. android XML解析详解(封装好的工具类)
  3. Android微信小程序原理,微信小程序事件流原理解析
  4. Leetcode 136.只出现一次的数字 (每日一题 20210714)
  5. 累加出整个范围所有的数最少还需要几个数
  6. Bag of Words(BOW)模型
  7. TRMF 辅助论文:最小二乘法复现TRMF
  8. 深入推荐引擎相关算法 - 聚类
  9. 7个示例科普CPU Cache
  10. Python 处理CSV文件