【问题标题】:@Transactional is not rolling back db transaction@Transactional 没有回滚数据库事务
【发布时间】:2018-05-26 23:15:32
【问题描述】:

我正在尝试在我的一种方法中使用@Transactional。以下场景:

场景:我将 2 个文件从一个文件夹复制到另一个文件夹,并希望在表中插入一条记录,其中包含文件详细信息,例如 file_namefile_location等

方法:这里我先插入一条记录,然后实际移动文件。这个方法被注释为@Transactional

预期:现在在移动文件之前,我正在检查,如果这两个文件都存在于源目录中。如果它们在源代码中不存在,那么我将抛出 RuntimeException() 这应该回滚插入语句。

实际:抛出异常后插入条目没有回滚。

@Transactional
private static void moveFilesAndUpdateDB(srcFile1, srcFile2, destinationDir) throws RuntimeException
{
    jdbcTemplate.update("insert into ......");
    Boolean sourceFileExists = sourceFilePresentCheck(srcFile1, srcFile2);
    if(sourceFileExists)
    {
        //code to dopy files
    }
    else
    {
        throw new RuntimeException();
    }
}

在抛出 RuntimeException 之后,插入条目不会被回滚。

【问题讨论】:

  • 它可能取决于多种因素。你怎么称呼这个?是bean的方法吗?您是否从另一个用@Transactional 注释的方法调用该方法?你拦截异常了吗?
  • 你不能使私有方法具有事务性,它们不能被代理。
  • @StanislavL 我将此方法称为简单的方法调用。麸皮的方法和其他事务方法都不是。我通过执行throw new RuntimeException() 来拦截上面代码中提到的 else 子句中的异常
  • @Transactional on private 方法不起作用。 @Transactional 上的 static 方法不起作用。你正在做这两个......
  • 是的.. 我现在删除了 privatestatic

标签: spring sql-insert jdbctemplate rollback transactional


【解决方案1】:

在您的情况下,@Transactional 只是被忽略了。相反,事务是在调用此事务的方法中的上方某处打开的。

@Transactional 适用于 Spring bean 和 publicstatic 方法。当创建 bean 时,Spring 会创建一个代理来评估事务打开/提交/回滚逻辑。

修复:

  1. 将类设为 Bean
  2. 使方法非staticpublic
  3. 检查调用方法事务。要忽略它,请添加传播 REQUIRES_NEW 以打开新的单独事务。

【讨论】:

  • 感谢您的帮助@StanislavL.. 你能告诉我我需要做什么来制作类 Bean 吗?我应该将哪个类转换为 Bean.. 我对 Spring 框架很陌生.. 所以无法理解.. 要求您解释一下.. 帮助表示感谢.. 非常感谢!
  • 包含 moveFilesAndUpdateDB 方法的类。解释得太宽泛了。最好阅读一下 Spring 的工作原理以及 Transactional 在 Spring 中的工作原理。
  • 当然 StanislavL.. 任何关于我需要做的代码的参考链接也会对我有所帮助.. 如果你有请分享
  • 我认为不只有一个示例或链接。最好用谷歌搜索,因为我不知道适合初学者的好资源。此外,在这里寻找库或教程是题外话。
【解决方案2】:

除了上面的答案,还需要在@Transactional后面加上(rollbackFor = RuntimeException.class)。

@Transactional(rollbackFor = RuntimeException.class)
private static void moveFilesAndUpdateDB(srcFile1, srcFile2, destinationDir) throws RuntimeException
{
  jdbcTemplate.update("insert into ......");
  Boolean sourceFileExists = sourceFilePresentCheck(srcFile1, srcFile2);
  if(sourceFileExists)
  {
    //code to dopy files
  }
  else
  {
    throw new RuntimeException();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2017-07-27
    • 2020-06-05
    • 1970-01-01
    相关资源
    最近更新 更多