请教下这里的事务为什么不回滚。。

2020-09-01 18:51:38 +08:00
 javaWeber

代码大概如下:

@Service
public class UserServiceImpl implements UserService {

	@Transactional
	public void insertA() throws Exception {		
		roleDao.insert(role);	//在角色表插入数据
		
                insertB();
	}


	@Transactional
	public int insertB() throws Exception {
		userDao.insert(user);	//在用户表插入的数据有重复主键
	}
	
}

A 方法用 roleDao 在角色表插入数据,然后调用 B 方法。

B 方法里面,用 userDao 插入用户表的数据存在重复主键。

两个方法都加了 @Transactional,B 方法在插入用户表时肯定不会成功,

那么事务会回滚,A 方法中的插入角色表应该也会回滚才对吧??

但是不知道为什么每次 A 方法的角色表的数据还是成功插入了。。

3483 次点击
所在节点    程序员
20 条回复
751327
2020-09-01 19:05:09 +08:00
insertA 这个方法是 UserServiceImpl 里面的方法调用吗
skypyb
2020-09-01 19:17:26 +08:00
这里 UserServiceImpl 实际上是在调用"自己"的方法, 而不是 Spring 代理的类的方法。
javaWeber
2020-09-01 19:17:49 +08:00
@751327 insertA 这个方法是 UserServiceImpl 里面的方法调用吗
==========================================
insertA ()只在控制层调用了。
mahogany
2020-09-01 19:18:12 +08:00
嵌套事务?
skypyb
2020-09-01 19:19:45 +08:00
上边说有点不对。 你 A 既然加了事务,那 B 加不加都无所谓了。 是不是抛的异常不是运行时异常啊 = =
javaWeber
2020-09-01 19:30:33 +08:00
@skypyb 上边说有点不对。 你 A 既然加了事务,那 B 加不加都无所谓了。 是不是抛的异常不是运行时异常啊
=============================================================
这里后台报错提示的异常是 DuplicateKeyException,这个异常也是 RuntimeException 的子类。。

dao 层那边是直接在方法后面 throws Exception 。。这个有影响么?
skypyb
2020-09-01 19:45:26 +08:00
@javaWeber #6 Spring 只处理运行时异常, 受检异常无视的。 如果抛出的是受检异常是就可能出现改了不回滚的情况。
qgs
2020-09-01 19:59:25 +08:00
aitaii
2020-09-01 21:28:16 +08:00
建议了解一下 spring 是如何开启事务的,这样就明白为什么没有起作用了。
关键词 spring 事务 原理 aop 动态代理
javaWeber
2020-09-01 21:33:27 +08:00
怀疑是自调用,或者非运行时异常导致的。

我直接写到一个方法里面,抛的异常也改成了运行时异常。

用户表插入重复主键的数据,插入失败。

而在同一个方法里面,在角色表插入数据,最后却插入成功了。。

事务还是没有回滚啊。好奇怪。。

如下所示:
```
@Service
public class UserServiceImpl implements UserService {

@Transactional
public void insertA() throws RuntimeException {
roleDao.insert(role); //在角色表插入数据

userDao.insert(user); //在用户表插入的数据有重复主键
}

}
```
AmosAlbert
2020-09-01 23:31:26 +08:00
insertB()没有被增强
10Buns
2020-09-01 23:51:31 +08:00
自调用时,并不是调用代理累的方法,自然 Spring 事务不会生效了
wakzz
2020-09-02 00:18:49 +08:00
因为是内部直接调用,没有走代理,所以基于代理的事务就不生效了
Xbluer
2020-09-02 04:22:07 +08:00
也许只是 auto commit 了
xuanbg
2020-09-02 07:17:47 +08:00
同一个类里面的不行,insertB 放到 roleDao 类里面就好。

@Service
public class UserServiceImpl implements UserService {

@Transactional
public void insertA() throws Exception {
roleDao.insert(role); //在角色表插入数据

roleDao.insertB();
}
}
wellR
2020-09-02 08:46:02 +08:00
调用 b 时,没有走 aop,应该在此 service 中注入自身,用这个注入的实例去调用 b
pierswu
2020-09-02 08:48:47 +08:00
你在 insertA 设置里面设置一个断点,看看调用堆栈里面有没有事务的 aop,我怀疑你的事务根本没生效
dbkx
2020-09-02 10:27:32 +08:00
事实上,如果使用 @Transaction 方法里嵌套调用的是同一个类的方法,spring 代理会忽略嵌套方法的 @Transaction 配置。但是,如果是其他注入对象的方法,那么 @Transaction 配置就会生效。
dengjunwen
2020-09-02 11:10:25 +08:00
@xuanbg 看下你的调用代码。现在 问题应该出现在调用部分和 transaction 配置部分
Habyss
2020-09-02 14:36:40 +08:00
楼主代码是 `同类中事务方法调用事务方法, 不会出现事务失效问题, 但是却会出现事务传播失效问题`
多问一句, 你这个项目有用 shiro 之类的权限管理吗?
如果用了的话, 有在相关权限配置类里面注入这个 Service 类吗?

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

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

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

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

© 2021 V2EX