请考虑以下代码:
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:
请注意,刷新与提交事务不同。如果 您的操作在事务的上下文中执行,刷新 将执行SQL更新,但数据库将保存其更改 事务队列并且仅在事务时完成更新 提交。
我们在事务完成之前调用serpService.submitKeyword
。该方法启动了一个全新的交易,我们的serpKeyword
不可用。将其更改为REQUIRED
是有效的,因为我们现在正在父事务的上下文中运行。
答案 0 :(得分:0)
我认为堆栈的某些部分是懒惰的。我使用Hibernate遇到了这种行为,如果这就是你正在使用的。我不确定这是一个经过批准的操作,但您可以在调用submitKeyword
之前清除会话,如下所示:
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()
会奏效。如果您在会话中有其他对象,则需要。你需要通过存储他们的id和.get()
来解除这些问题。