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

springboot service 事物回滚的问题

  •  
  •   strongme ·
    strongme · 2017-11-22 13:43:01 +08:00 · 7461 次点击
    这是一个创建于 2556 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有如下代码: https://gitee.com/strongme/codes/g0157y3zxhmn2bfurwvtc22 save 方法中某个位置抛出异常,整个事务没有回滚。这是什么问题呢?

    第 1 条附言  ·  2017-11-22 15:29:29 +08:00
    https://gitee.com/strongme/basic-springboot
    代码我传这里了,可以下下来看看,就是 UserService 里面所有事务都不起作用
    第 2 条附言  ·  2017-11-23 09:36:07 +08:00
    我单独把 user 的 save 方法放到一个新的 Service,事务是正常的!
    然而原来那个 UserSerivce 里面的需要事务的内容,还是不行!
    要哭
    第 3 条附言  ·  2017-11-23 14:37:34 +08:00
    已经解决了,谢谢各位,具体解决办法见仓库。
    是 shiro 的问题
    22 条回复    2017-11-29 09:15:01 +08:00
    neoblackcap
        1
    neoblackcap  
       2017-11-22 14:34:54 +08:00
    抛 ServiceException,但是没有回滚?
    JRay
        2
    JRay  
       2017-11-22 15:09:56 +08:00
    不是应该抛出去嘛。。
    strongme
        3
    strongme  
    OP
       2017-11-22 15:29:58 +08:00
    @neoblackcap 朋友可以下下来工程跑跑试试,我要难受~~
    weics
        4
    weics  
       2017-11-22 16:34:12 +08:00
    看下 ServiceException 继承的是 check 异常还是 uncheck 异常,顺便把 save 方法上面的 Transactional 去除,只保留 service 上面的注解
    strongme
        5
    strongme  
    OP
       2017-11-22 16:43:24 +08:00
    @weics 朋友你说的这两个我都试过了,但是还是不行
    weics
        6
    weics  
       2017-11-22 16:49:40 +08:00
    @strongme
    数据库的引擎是否支持代码回滚?
    strongme
        7
    strongme  
    OP
       2017-11-22 16:55:21 +08:00
    @weics 是支持的,别的 Service 没问题,就是 UserService
    hustlike
        8
    hustlike  
       2017-11-22 16:58:27 +08:00
    你是不是要配置一个 transactionManager 的 bean ?
    weics
        9
    weics  
       2017-11-22 17:01:21 +08:00
    @strongme
    在别的 service 里面注入 user 的 dao 层,然后试试添加操作,看别的 service 能不能回滚,定位一下
    tr0uble
        10
    tr0uble  
       2017-11-22 17:14:48 +08:00
    看下 UserService 是不是一个代理类,回滚你明确指定了 ServiceException,是否有这种异常抛出
    strongme
        11
    strongme  
    OP
       2017-11-22 17:56:14 +08:00
    @tr0uble 我先查查什么叫代理类~~
    strongme
        12
    strongme  
    OP
       2017-11-22 17:58:56 +08:00
    @tr0uble 应该算是代理类
    关键是其他的都正常····
    就这个 UserService 不正常
    lsyhyp
        13
    lsyhyp  
       2017-11-22 18:07:40 +08:00
    贴一下异常栈?
    seaswalker
        14
    seaswalker  
       2017-11-23 07:40:03 +08:00 via iPhone
    从哪里调的这个方法
    strongme
        15
    strongme  
    OP
       2017-11-23 09:12:05 +08:00
    @hustlike 有事务的 Service 有好多个呢,但是唯独这个 UserService 不起作用,有时间的话可以看看我传的那个代码~~好心塞
    strongme
        16
    strongme  
    OP
       2017-11-23 09:12:25 +08:00
    @weics 好办法!我去试试
    strongme
        17
    strongme  
    OP
       2017-11-23 09:14:21 +08:00
    @lsyhyp 朋友这到不是异常的问题,是事务的问题呢,异常是我手动故意抛出来的,要是测试事务回滚问题
    strongme
        18
    strongme  
    OP
       2017-11-23 09:15:17 +08:00
    @seaswalker 朋友是在 Controller 里面调用呢
    kaka8wp
        19
    kaka8wp  
       2017-11-23 09:44:43 +08:00
    在 springBoot 使用事物时,发现事务并没有正常执行,没有进行回滚。
    [java] view plain copy
    @GetMapping("add")
    @ResponseBody
    @Transactional
    public void add(String companyName,String name){
    companyDao.add(companyName);
    try {
    userDao.addUser(name);
    }catch (DuplicateKeyException e){//这里在数据库将 name 设置成 unique key
    logger.error("添加失败。姓名:[ {} ],已存在",name);
    return new MyException("添加失败,名字已存在");//自定义异常 继承 Exception
    }
    }


    上述姓名重复时发现,公司名称依然添加成功,并没有进行回滚操作。

    分析:默认 spring 事务只在发生未被捕获的 RuntimeException 时才回滚。
    spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样 aop 代理才能捕获到方法的异常,才能进行回滚,默认情况下 aop 只捕获 RuntimeException 的异常,但可以通过配置来捕获特定的异常并回滚
    换句话说在 service 的方法中不使用 try catch 或者在 catch 中最后加上 throw new runtimeexcetpion (),这样程序异常时才能被 aop 捕获进而回滚
    解决办法:
    1.首先确认数据库支持事务。即为 InnoDB。
    方案一:手动回滚。给注解加上参数如:@Transactional(rollbackFor=Exception.class)
    方案二:如上述分析。MyException 改为继承 RuntimeException 的异常。并且在 service 上层要继续捕获这个异常并处理
    方案三:在 service 层方法的 catch 语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常

    链接: http://blog.csdn.net/bestlovelymin/article/details/74942932
    strongme
        20
    strongme  
    OP
       2017-11-23 14:37:07 +08:00
    @kaka8wp 朋友我解决了,是 shiro 的问题,具体可以去仓库看看代码,是使用配置的问题,天生的
    jack80342
        21
    jack80342  
       2017-11-28 23:10:08 +08:00
    最近翻译了 Spring Boot 最新的官方文档,欢迎 Fork,https://www.gitbook.com/book/jack80342/spring-boot/details
    johnniang
        22
    johnniang  
       2017-11-29 09:15:01 +08:00 via Android
    @kaka8wp 注解 @Transactional 能在 Controller 方法上加?你确定开服务器后能访问到这个 add?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   997 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:07 · PVG 06:07 · LAX 14:07 · JFK 17:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.