为什么我的GORM对象不保存到数据库?

时间:2013-04-08 17:58:04

标签: grails transactions gorm grails-2.0

请考虑以下代码:

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是有效的,因为我们现在正在父事务的上下文中运行。

1 个答案:

答案 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()来解除这些问题。