V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
牛客网
javaWeber
V2EX  ›  程序员

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

  •  
  •   javaWeber · 57 天前 · 2076 次点击
    这是一个创建于 57 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码大概如下:

    @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 方法的角色表的数据还是成功插入了。。

    20 条回复    2020-09-02 14:36:40 +08:00
    751327
        1
    751327   57 天前
    insertA 这个方法是 UserServiceImpl 里面的方法调用吗
    skypyb
        2
    skypyb   57 天前
    这里 UserServiceImpl 实际上是在调用"自己"的方法, 而不是 Spring 代理的类的方法。
    javaWeber
        3
    javaWeber   57 天前
    @751327 insertA 这个方法是 UserServiceImpl 里面的方法调用吗
    ==========================================
    insertA ()只在控制层调用了。
    mahogany
        4
    mahogany   57 天前
    嵌套事务?
    skypyb
        5
    skypyb   57 天前
    上边说有点不对。 你 A 既然加了事务,那 B 加不加都无所谓了。 是不是抛的异常不是运行时异常啊 = =
    javaWeber
        6
    javaWeber   57 天前
    @skypyb 上边说有点不对。 你 A 既然加了事务,那 B 加不加都无所谓了。 是不是抛的异常不是运行时异常啊
    =============================================================
    这里后台报错提示的异常是 DuplicateKeyException,这个异常也是 RuntimeException 的子类。。

    dao 层那边是直接在方法后面 throws Exception 。。这个有影响么?
    skypyb
        7
    skypyb   57 天前
    @javaWeber #6 Spring 只处理运行时异常, 受检异常无视的。 如果抛出的是受检异常是就可能出现改了不回滚的情况。
    qgs
        8
    qgs   57 天前
    aitaii
        9
    aitaii   57 天前
    建议了解一下 spring 是如何开启事务的,这样就明白为什么没有起作用了。
    关键词 spring 事务 原理 aop 动态代理
    javaWeber
        10
    javaWeber   57 天前
    怀疑是自调用,或者非运行时异常导致的。

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

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

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

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

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

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

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

    }
    ```
    AmosAlbert
        11
    AmosAlbert   57 天前
    insertB()没有被增强
    10Buns
        12
    10Buns   57 天前
    自调用时,并不是调用代理累的方法,自然 Spring 事务不会生效了
    wakzz
        13
    wakzz   57 天前
    因为是内部直接调用,没有走代理,所以基于代理的事务就不生效了
    Xbluer
        14
    Xbluer   57 天前 via iPhone
    也许只是 auto commit 了
    xuanbg
        15
    xuanbg   57 天前
    同一个类里面的不行,insertB 放到 roleDao 类里面就好。

    @Service
    public class UserServiceImpl implements UserService {

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

    roleDao.insertB();
    }
    }
    wellR
        16
    wellR   57 天前 via Android
    调用 b 时,没有走 aop,应该在此 service 中注入自身,用这个注入的实例去调用 b
    pierswu
        17
    pierswu   57 天前
    你在 insertA 设置里面设置一个断点,看看调用堆栈里面有没有事务的 aop,我怀疑你的事务根本没生效
    dbkx
        18
    dbkx   57 天前
    事实上,如果使用 @Transaction 方法里嵌套调用的是同一个类的方法,spring 代理会忽略嵌套方法的 @Transaction 配置。但是,如果是其他注入对象的方法,那么 @Transaction 配置就会生效。
    dengjunwen
        19
    dengjunwen   57 天前 via Android
    @xuanbg 看下你的调用代码。现在 问题应该出现在调用部分和 transaction 配置部分
    Habyss
        20
    Habyss   57 天前
    楼主代码是 `同类中事务方法调用事务方法, 不会出现事务失效问题, 但是却会出现事务传播失效问题`
    多问一句, 你这个项目有用 shiro 之类的权限管理吗?
    如果用了的话, 有在相关权限配置类里面注入这个 Service 类吗?
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3970 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 10:08 · PVG 18:08 · LAX 03:08 · JFK 06:08
    ♥ Do have faith in what you're doing.