【问题标题】:Data not persisted after return from service从服务返回后数据未保留
【发布时间】:2025-12-30 03:05:11
【问题描述】:

让我先说我的代码昨天还在工作。我将我的提交回滚到它工作的时间。

唯一不同的是今天运行了迁移以从某些表中删除某些列。我看不出这会如何影响它

我正在执行 google oauth 身份验证,并且在来自 google 的回调 url 中,我正在执行大量保存/更新/等操作。我的控制器调用一个可以完成所有操作的服务。如果我在 return 语句所在的断点处查询数据,我可以看到数据。没有例外、验证错误或任何会让我相信任何错误的事情。有什么想法吗?

class MyController {

  def myService

  def callback() {
    myService.update()
    //At this point when I run X.get(1) it is returning null
    redirect uri: "..."
  }
}

@Transactional
class MyService {

  def update() {
    ...
    //If I break at this return statement I can run X.get(1) and it returns
    return someData;
  }
}

编辑:我找到了原因,但我不明白这是怎么发生的。我最终打电话给userDetailsService.loadUserByUsername。该方法正在抛出NoStackUsernameNotFoundException。我在我的代码中发现了该异常,但是无论如何它都会导致事务回滚。

【问题讨论】:

  • 事务中抛出的任何异常,即使你捕捉到并处理,也会导致事务回滚。
  • 你捕获事务内部还是外部的异常?
  • @rcgeorge23 ​​你确定吗?你能指出我在文档中这样说的地方吗?我一直觉得捕获的异常并没有回滚事务
  • @holmis83 spring security 有自己的 withTransaction 块,它在其中抛出异常:github.com/grails-plugins/grails-spring-security-core/blob/…。我在它被调用的地方准确地捕捉到了这个异常。

标签: grails spring-security grails-2.5


【解决方案1】:

事务过程中抛出的任何异常,即使你捕获并处理它,也会导致事务回滚。

要解决这个问题,您有几个选择:

  1. 在引发异常之前执行检查,并且不要在您知道会引发异常的情况下执行违规代码
  2. 自己处理事务 -

在你的服务中,设置

static transactional = false

然后声明自己的交易块:

MyDomain.withTransaction { tx ->
    try {
        userDetailsService.loadUserByUsername(...)
    } catch (NoStackUsernameNotFoundException e) {
        log.warn("Can't load user...")
    } 

    //stuff you try to persist here will 
    //be written to the database successfully 
    //despite the NoStackUsernameNotFoundException
    //being thrown & caught
}

【讨论】: