考虑以下代码:
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)
返回空值。什么可能会阻止此保存?
编辑
改变REQUIRES_NEW
至REQUIRED
似乎可以解决问题。这就是我认为正在发生的事情。
调用 serpService.submitKeyword
的代码位于服务方法内。据我了解,服务方法的默认传播策略为 REQUIRED
。由于所有这些数据库写入都发生在事务的上下文中,因此写入会在数据库中排队,但在事务完成之前不会实际对数据库执行,根据 docs :
Note that flushing is not the same as committing a transaction. If your actions are performed in the context of a transaction, flushing will execute SQL updates but the database will save the changes in its transaction queue and only finalize the updates when the transaction commits.
我们调用serpService.submitKeyword
在我们的交易真正完成之前。该方法启动一个全新的事务,其中我们的 serpKeyword
不可用。将其更改为 REQUIRED
之所以有效,是因为我们现在是在父事务的上下文中进行操作的。
最佳答案
我认为堆栈的某些部分很懒。我在 Hibernate 中遇到过这种行为,如果你正在使用 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()
来取出它们。
关于grails - 为什么我的 GORM 对象没有保存到数据库中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15885745/