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

2019-11-23 09:49:17 +08:00
 running17
a 方法中需要先对数据进行删除后调用 b 方法重新写入数据,删除和新增的数据的 project_id 字段值相同,且删除时是根据该字段来的,在同个事务下的话现在是会导致新增的数据会被直接删除掉,虽然 console 打印出来 delete 是先执行了后再执行的 insert 的。然后把 b 方法的代码复制到 a 中直接执行就没有问题,看了 console 的打印的日志,区别就是 a 调 b 时开启了事务,而单 a 执行时没有事务,有点疑惑,恳请大佬们解疑,然后是否可以在 a 调用 b 时不开启事务?
5283 次点击
所在节点    Java
16 条回复
zhoulifu
2019-11-23 09:57:22 +08:00
A 中 a 方法开启事务,并将 B 中 b 方法事务的传播级别改为 PROPAGATION_SUPPORTS
zhoulifu
2019-11-23 09:58:09 +08:00
@zhoulifu 更正,应改为 PROPAGATION_REQUIRES_NEW
zjsxwc
2019-11-23 10:00:23 +08:00
“在同个事务下的话现在是会导致新增的数据会被直接删除掉” 什么意思啊
zhoulifu
2019-11-23 10:00:38 +08:00
眼花了,PROPAGATION_REQUIRED
= =|||
running17
2019-11-23 10:02:49 +08:00
@zhoulifu b 方法是 A 继承来的,是否有不修改 b 的事务传播级别的方式?
running17
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
2019-11-23 10:08:44 +08:00
看样子楼主你用的应该 spring 的事务管理,如果是的话,A 的 a 方法没有事务,而同一个类 A 下的 b 方法有事务,这时调用 a 不会开启事务的。因为 a 并没有被代理。

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

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

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

一直感觉楼主说的情况不会出现啊

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/622332

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX