V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
running17
V2EX  ›  Java

同个 service 下方法互相调用时的事务疑惑, A 下的 a 方法没有事务,但是 b 方法有事务,请问如何在 a 方法调用 b 方法的时候不开启事务

  •  
  •   running17 · 2019-11-23 09:49:17 +08:00 · 5033 次点击
    这是一个创建于 1588 天前的主题,其中的信息可能已经有所发展或是发生改变。
    a 方法中需要先对数据进行删除后调用 b 方法重新写入数据,删除和新增的数据的 project_id 字段值相同,且删除时是根据该字段来的,在同个事务下的话现在是会导致新增的数据会被直接删除掉,虽然 console 打印出来 delete 是先执行了后再执行的 insert 的。然后把 b 方法的代码复制到 a 中直接执行就没有问题,看了 console 的打印的日志,区别就是 a 调 b 时开启了事务,而单 a 执行时没有事务,有点疑惑,恳请大佬们解疑,然后是否可以在 a 调用 b 时不开启事务?
    16 条回复    2019-12-12 20:19:27 +08:00
    zhoulifu
        1
    zhoulifu  
       2019-11-23 09:57:22 +08:00   ❤️ 1
    A 中 a 方法开启事务,并将 B 中 b 方法事务的传播级别改为 PROPAGATION_SUPPORTS
    zhoulifu
        2
    zhoulifu  
       2019-11-23 09:58:09 +08:00
    @zhoulifu 更正,应改为 PROPAGATION_REQUIRES_NEW
    zjsxwc
        3
    zjsxwc  
       2019-11-23 10:00:23 +08:00   ❤️ 1
    “在同个事务下的话现在是会导致新增的数据会被直接删除掉” 什么意思啊
    zhoulifu
        4
    zhoulifu  
       2019-11-23 10:00:38 +08:00   ❤️ 1
    眼花了,PROPAGATION_REQUIRED
    = =|||
    running17
        5
    running17  
    OP
       2019-11-23 10:02:49 +08:00
    @zhoulifu b 方法是 A 继承来的,是否有不修改 b 的事务传播级别的方式?
    running17
        6
    running17  
    OP
       2019-11-23 10:06:33 +08:00
    @zjsxwc
    是这样的,先执行了 delete from xx where project_id = 'aaaa',
    后执行了 insert insert xx (project_id, name) values ('aaaa', 'bbbb')
    因为开启了事务,后面执行的 name 为'bbbb'执行成功了,但数据库中没有找到记录
    没有事务的情况下能找到
    cxshun
        7
    cxshun  
       2019-11-23 10:08:44 +08:00   ❤️ 1
    看样子楼主你用的应该 spring 的事务管理,如果是的话,A 的 a 方法没有事务,而同一个类 A 下的 b 方法有事务,这时调用 a 不会开启事务的。因为 a 并没有被代理。

    如果确实出现你说的情况,看一下是不是这个 A 类被注解为事务了,导致了整个类都要求用事务
    running17
        8
    running17  
    OP
       2019-11-23 10:11:04 +08:00
    @cxshun
    b 方法上是注解了 @Transactional( rollbackFor = {Exception.class}),
    a 方法上没有注解,A 类上也没有注解,b 方法是 A 类从 B 类继承过来的
    zhoulifu
        9
    zhoulifu  
       2019-11-23 10:16:07 +08:00
    @running17
    如果是继承下来的话,在同一个类内部调用应该是不会开启事务的
    开一下业务模块 TRACE 级别的 log,看看能不能找到什么吧
    wysnylc
        10
    wysnylc  
       2019-11-23 10:31:32 +08:00   ❤️ 1
    我的办法是不用事务,事务传播级别太恶心了而且在分布式下事务是一个巨大的拖累
    用代码回滚会比较好
    Aruforce
        11
    Aruforce  
       2019-11-23 11:03:13 +08:00 via Android
    你们真逗…b 改成 support… 还有不要 this.b 这样调用…
    w292614191
        12
    w292614191  
       2019-11-23 11:12:49 +08:00
    类开启事务,就全有事务了。简单明了。
    我还把其他 service 注入到另一个 service 类,大家都有事务,相互调用,瞎搞胡搞,屁事没有。
    Aruforce
        13
    Aruforce  
       2019-11-23 11:15:46 +08:00 via Android   ❤️ 1
    @Aruforce 如果你现在事务的模式为 proxy 而不是 aspectj 的话…this.b 调应该开启不了事务的出现不了你这种情况…但是根据前面的那些…你们应该是 aspectj 这种模式…

    Support 是有事物则加入…没事务自己不开新事务…

    如果你想实现…a this.b 不开事务而直接使用 b 要开事务的话你需要改成 proxy 模式…b 改成 required… 这么改你最好和组长商量下…使用 aspectj 这种模式是有原因的…
    cxshun
        14
    cxshun  
       2019-11-28 11:00:09 +08:00
    @running17 #8 这样不应该会有事务的,建议你开一下 trace 日志,看下是不是确定被代理了。你可以在`spring`初始化的时修改调试一下,看返回的 bean 具体是不是被代理
    zjsxwc
        15
    zjsxwc  
       2019-12-12 19:51:07 +08:00 via Android
    @running17 #6

    是指开启事务后执行这样的 sql 吗
    begin transaction;
    insert insert xx (project_id, name) values ('aaaa', 'bbbb');
    delete from xx where project_id = 'aaaa';
    commit;

    而不开启事务执行这样的 sql 吗
    delete from xx where project_id = 'aaaa';
    insert insert xx (project_id, name) values ('aaaa', 'bbbb');
    zjsxwc
        16
    zjsxwc  
       2019-12-12 20:19:27 +08:00 via Android
    https://juejin.im/entry/5836572767f3560065f1939b

    一直感觉楼主说的情况不会出现啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2431 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 16:04 · PVG 00:04 · LAX 09:04 · JFK 12:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.