考虑以下代码:

if (!serpKeyword) {
    serpKeyword = new SerpKeyword(
            keyword: searchKeyword,
            geoKeyword: geoKeyword,
            concatenation: concatenation,
            locale: locale
    )
    serpKeyword.save(flush: true, failOnError: true)
}

serpService.submitKeyword(serpKeyword, false)

这是submitKeyword方法:
@Transactional(propagation = Propagation.REQUIRES_NEW)
boolean submitKeyword(keywordToSubmit, boolean reset) {
    def keyword = SerpKeyword.get(keywordToSubmit.id)

调用serpKeyword.save不会引发任何错误,但是当我进入submitKeyword方法时,SerpKeyword.get(keywordToSubmit.id)返回null。有什么可以防止这种方法节省?

编辑

REQUIRES_NEW更改为REQUIRED似乎可以解决问题。我认为这是正在发生的事情。

调用serpService.submitKeyword的代码位于服务方法中。据我了解,服务方法的默认传播策略为REQUIRED。根据docs,由于所有这些数据库写操作都是在事务上下文中发生的,因此这些写操作会在数据库中排队,但直到事务完成后才对数据库实际执行:



我们实际上完成交易之前调用serpService.submitKeyword。该方法将启动一个全新的事务,其中我们的serpKeyword不可用。将其更改为REQUIRED是可行的,因为我们现在在父事务的上下文中进行操作。

最佳答案

我认为堆栈的某些部分很懒。如果您正在使用Hibernate,我已经遇到了这种情况。我不确定这是否已获批准,但是您可以在调用submitKeyword之前清除 session ,如下所示:

long keywordId = serpKeyword.id
SerpKeyword.withSession{it.clear()}
serpService.submitKeyword(keywordId, false)

然后将方法更改为:
@Transactional(propagation = Propagation.REQUIRES_NEW)
boolean submitKeyword(keywordId, boolean reset) {
  def keyword = SerpKeyword.get(keywordId)

然后,我敢打赌.get()将起作用。如果 session 中还有其他对象,则需要。您将需要通过存储它们的ID并对其进行.get()来解除它们。

10-06 01:23