考虑以下代码:
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()
来解除它们。