• 请不要在回答技术问题时复制粘贴 AI 生成的内容
javaWeber
V2EX  ›  程序员

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

  •  
  •   javaWeber · Sep 1, 2020 · 5069 views
    This topic created in 2254 days ago, the information mentioned may be changed or developed.

    代码大概如下:

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

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

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

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

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

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

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

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

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

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

    @Service
    public class UserServiceImpl implements UserService {

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

    roleDao.insertB();
    }
    }
    wellR
    wellR
    Sep 2, 2020 via Android
    16
    调用 b 时,没有走 aop,应该在此 service 中注入自身,用这个注入的实例去调用 b
    yigedala
    yigedala
    Sep 2, 2020
    17
    你在 insertA 设置里面设置一个断点,看看调用堆栈里面有没有事务的 aop,我怀疑你的事务根本没生效
    dbkx
    dbkx
    Sep 2, 2020
    18
    事实上,如果使用 @Transaction 方法里嵌套调用的是同一个类的方法,spring 代理会忽略嵌套方法的 @Transaction 配置。但是,如果是其他注入对象的方法,那么 @Transaction 配置就会生效。
    dengjunwen
    dengjunwen
    Sep 2, 2020 via Android
    19
    @xuanbg 看下你的调用代码。现在 问题应该出现在调用部分和 transaction 配置部分
    Habyss
    Habyss
    Sep 2, 2020
    20
    楼主代码是 `同类中事务方法调用事务方法, 不会出现事务失效问题, 但是却会出现事务传播失效问题`
    多问一句, 你这个项目有用 shiro 之类的权限管理吗?
    如果用了的话, 有在相关权限配置类里面注入这个 Service 类吗?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1418 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 22:27 · PVG 06:27 · LAX 14:27 · JFK 17:27
    ♥ Do have faith in what you're doing.