• 事务 还有这些用法,之前都不知道


    transationTemplate.execute 的写法 第一次 碰到,我之前是 controller -> biz -> service -> mapper 然后用 @Transation 注解搞定事务,至于 同一个类的 方法之间调用,在biz 层就规避了

    不懂就问

    首先 同一个类中 方法调用因为没有 走 aop 所以 事务不生效,这个应该没毛病吧

    问了人家,人家说 能解决 同一类中的 不同方法调用的 事务问题,我不太信。。验证下,如果能行,我以后加入

    Spring事务失效的场景

    1. 非public修饰
    2. final修饰也会失效, 动态代理需要重写方法才能生效事务, final修饰则无法重写
    3. static修饰也会失效
    4. 吞了异常, catch住没有抛给spring
    5. 抛了错误的异常, catch住手动抛Exception则不会回滚, 因为spirng事务只会处理RuntimeException和Error
    6. 同一个类中的方法进行互相调用

    准备代码

    1. public void a() {
    2. // transactionTemplate.execute(transactionStatus -> {
    3. // b();
    4. // c();
    5. // return true;
    6. // });
    7. Version version = new Version();
    8. version.setVersionName("test00");
    9. version.setProjectId(1L);
    10. versionService.save(version);
    11. b();
    12. c();
    13. }
    14. @Transactional(rollbackFor = Exception.class)
    15. public void b() {
    16. Version version = new Version();
    17. version.setVersionName("test01");
    18. version.setProjectId(1L);
    19. versionService.save(version);
    20. }
    21. @Transactional(rollbackFor = Exception.class)
    22. public void c() {
    23. Version version = new Version();
    24. version.setVersionName("test02");
    25. version.setProjectId(1L);
    26. versionService.save(version);
    27. int i = 1 / 0;
    28. }
    29. 复制代码

    第一次实验 嗯嗯 确实数据库插入了3条,事务没有生效嘛

    那按照大哥的说法 如果用他那种写法 就能保证事务了?

    改下代码 试验下

    1. public void a() {
    2. transactionTemplate.execute(transactionStatus -> {
    3. Version version = new Version();
    4. version.setVersionName("test00");
    5. version.setProjectId(1L);
    6. versionService.save(version);
    7. b();
    8. c();
    9. return true;
    10. });
    11. }
    12. 复制代码

    想想 如果是和大哥的想法一样 数据库应该是 没有插入,好 执行下

    嗯嗯 是的 确实没有数据库插入,但是为什么呢? 嗯嗯 大哥说得对

    猜想

    我第一想法 就是 它这么写 就相当于 我们之前biz 层 对 service 层的调用,自然而言 就保证了事务,毕竟实现了 不同类的调用嘛

    验证下

    1. @Nullable
    2. public T execute(TransactionCallback action) throws TransactionException {
    3. //判断transactionManager 是否为空 嗯嗯 没毛病
    4. Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
    5. //
    6. if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
    7. return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this, action);
    8. } else {
    9. TransactionStatus status = this.transactionManager.getTransaction(this);
    10. Object result;
    11. try {
    12. //执行 真正的代码
    13. result = action.doInTransaction(status);
    14. } catch (Error | RuntimeException var5) {
    15. this.rollbackOnException(status, var5);
    16. throw var5;
    17. } catch (Throwable var6) {
    18. this.rollbackOnException(status, var6);
    19. throw new UndeclaredThrowableException(var6, "TransactionCallback threw undeclared checked exception");
    20. }
    21. this.transactionManager.commit(status);
    22. return result;
    23. }
    24. }
    25. 复制代码

    扩展

    transactionTemplate.executeWithoutResult

    在看 transactionTemplate 方法的时候 发现一个 executeWithoutResult 方法,嗯嗯 他是干什么的

    看个名字应该是 没有返回值 嗯嗯

    1. default void executeWithoutResult(Consumer<TransactionStatus> action) throws TransactionException {
    2. this.execute((status) -> {
    3. action.accept(status);
    4. return null;
    5. });
    6. }
    7. 复制代码

    这 。。。不就是套了一层,返回个null么

    TransactionSynchronization

    1. public class DoTransactionCompletion implements TransactionSynchronization {
    2. private Runnable runnable;
    3. public DoTransactionCompletion(Runnable runnable){
    4. this.runnable = runnable;
    5. }
    6. @Override public void afterCompletion(int status) {
    7. if(status == TransactionSynchronization.STATUS_COMMITTED){
    8. this.runnable.run();
    9. }
    10. }
    11. }
    12. 复制代码
    1. public class TransactionUtils {
    2. public static void doAfterTransaction(DoTransactionCompletion doTransactionCompletion){
    3. if(TransactionSynchronizationManager.isActualTransactionActive()){
    4. TransactionSynchronizationManager.registerSynchronization(doTransactionCompletion);
    5. }
    6. }
    7. public static void main(String[] args) {
    8. TransactionUtils.doAfterTransaction(new DoTransactionCompletion(() -> {
    9. //事务成功才做的操作
    10. }));
    11. }
    12. }
    13. 复制代码

    例子是 上面的main方法 实现的是 只有事务成功才会执行的操作

    其余的可以自己进行判断status 进行控制

    但是并不完美,这个写法 是有问题的

    1. 如果使用了 @Transaction REQUIRES_NEW的话 就会出现误完成
    2. 如果里面有多线程 ,也会导致 异常

    优化

    1. 我后来把事务的new 单独进行判断,把REQUIRES_NEW的 忽略了
    2. 多线程 之前进行过封装,分为了 1 在同一个事务中,一起提交 2 可以局部提交,局部完成,我根据之前的封装,继续判断,如果是 1 状态,我会执行这个完成操作,否则进行剔除
  • 相关阅读:
    数据治理项目成功的要点,企业培养数据要把握好关键环节
    基于神经气体网络的图像分割与量化(Matlab代码实现)
    pytorch-09.多分类问题
    “ /^A-Z:\\{1,2}^/:\*\?<>\|+\.(jpg|gif|png|bmp)$/i ”这个正则表达式的理解
    PCB - 封装焊盘阻焊层的检查
    PerformanceOne一站式性能测试平台
    安全狗受邀亮相第二届工控中国大会
    Linux之线程同步和生产者消费者模型
    ubuntu 18.04安装python3.7.5,并将 python 设定为python3, pip设定为pip3
    mysql使用orderby 不起作用
  • 原文地址:https://blog.csdn.net/m0_73311735/article/details/127786205