我已经搜索这个,但还是无法弄清楚我在做什么错。 打完电话后save()
域对象id
为null
。
我读过,如果保存对象时,有一个问题,它会发生,并且save(flush:true)
,如果是这样的话应该抛出一个错误,但它不是。 看看我的代码和输出:
def pic = new Picture(title:'XX', path:"XXX")
album.addToPictures(pic).save()
if(pic.validate())
println "no errors. New id: " + pic.id
else
println "with errors"
输出:
no errors. New id: null
而在使用冲洗时:真
def pic = new Picture(title:'XX', path:"XXX")
album.addToPictures(pic).save(flush:true)
if(pic.validate())
println "no errors. New id: " + pic.id
else
println "with errors"
输出:
no errors. New id: 17
正如你所看到的,有没有创建对象的任何错误,我应该能够得到id
只调用后,对象的save()
有任何想法吗?
谢谢
你是误会当一个对象实际上得到持久化到数据库的时间。 一个对象没有得到,当你调用持续obj.save()
当发生以下情况先发生者为准,它就会坚持:
- 其中保存(交易)被称为承诺
- 其中保存Hibernate的Session()被调用关闭
事务可以明确地启动
SomeDomainClass.withTransaction {
// code in here runs within a transaction
}
通常情况下,交易也被隐式开始每次调用一个服务方法
class MyService {
void doSomething () {
// code in here runs within a transaction
}
}
如果你不明确或含蓄地使用事务,保存的对象得到坚持,当Hibernate的Session关闭,这是(大致)的HTTP请求完成时。
但是,如果你调用someObject.save(flush: true)
你告诉Hibernate来坚持立即对象,这是为什么
album.addToPictures(pic).save(flush: true)
分配ID的Picture
的实例,但
album.addToPictures(pic).save()
当包封会话/交易结束后就会只分配了ID /承诺
更新
Futher您的意见
问题是,我想使用的ID作为文件我需要保存的名称的一部分。 怎么样,如果我得到一个保存文件时出错? 我应该使用一个明确的事务,并回滚?
是的,使用一个明确的交易,并保存该文件一旦你确定对象已被成功地坚持着,回滚事务,如果持续失败
def pic = new Picture(title:'XX', path:"XXX")
Picture.withTransaction { TransactionStatus status ->
try {
album.addToPictures(pic).save()
} catch(ex) {
status.setRollbackOnly()
throw ex
}
}
// At this point you can be sure pic has been persisted, so use pic.id to save the file
更新2
而且您的意见
我不想保存该文件一旦我敢肯定,对象已经成功地坚持着,但相反的,我想坚持的目标,一旦该文件已被成功保存。 所以,我要重新制定我的问题是“是否有配置Grails的,这样我可以知道那将被分配到新对象之前,该对象被有效保存在数据库中的ID的方法吗?”
你已经知道,
album.addToPictures(pic).save(flush:true)
会为您提供的ID Picture
实例,因此,如果你这样做在一个事务中,你可以得到的ID,而无需实际提交事务。 但是,我认为,如果你使用的是使用序列数据库(甲骨文,Postgres的)这只会工作。 像下面这样的东西应该工作
Picture.withTransaction { TransactionStatus status ->
try {
def pic = new Picture(title:'XX', path:"XXX")
album.addToPictures(pic).save(flush: true)
// pic.id should now be assigned, so save the file. I'm assuming an
// an exception will be thrown if saving the file fails
} catch(ex) {
// you may also want to try rolling back the file save here, i.e. delete it
status.setRollbackOnly()
throw ex
}
}
并保存(冲洗:真)应该抛出一个错误
这不是真的。 save(failOnError: true)
将导致异常被抛出。
没有什么是你的代码错误,也不是什么错,你所看到的行为。 如果不调用flush; save()
你想真正的插入发生之前访问生成的ID。 这就是为什么它是空的。
然而,迫使冲洗意志(有时)强制Hibernate来写,然后给你你期待的ID。 如果您需要的ID调用后立即save()
使用save(flush: true)
。 没有什么不妥。
文章来源: Grails. Id is null after calling save