我正在尝试使用GORM事件beforeInsert
和beforeUpdate
更新Grails中的一对多关联。目前beforeInsert
似乎正在运行,但beforeUpdate
总是在hibernate flush上抛出TransientObjectException
。
以下列方式映射域(一个例子,但希望足以得到这个想法):
class Part {
String xml
static hasMany = [screws: Screws]
static mapping = {
screws cascade: "all-delete-orphan"
}
}
class Screw {
static belongsTo = Part
}
我的更新和插入基本上做同样的事情,这个方法从beforeInsert
和beforeUpdate
调用(再次是一个代表性的例子):
private void augmentPartWithScrews() {
screws?.clear()
Set<Screw> parsedScrews = service.parseXmlAndReturnSetofScrews(xml)
parsedScrews.each {
addToScrews(it)
}
}
我所看到的是,当我创建一个新的Part它可以工作时,但是当我更新Part以便删除螺丝时,我在Hibernate的TransientObjectException
类中获得ForeignKeys
。我做了一些调试,发现在创建Part
的新实例时,对象作为已保存的实例进入函数getEntityIdentifierIfNotUnsaved
方法,但在更新时它们作为未保存的实例进入,因此是异常。
这是Grails 2.3.7和Hibernate插件3.6.10.10
答案 0 :(得分:1)
我们发现尝试在beforeInsert
或beforeUpdate
方法中执行插入或删除操作可能会非常痛苦。 withNewSession
几乎总是必不可少的,因为您在刷新会话时有效地尝试修改会话,从而导致Hibernate无法混淆。但是,使用withNewSession
时,screws
已加载到其他会话中,因此将在此新会话中分离。
有人认为在这种情况下您可以做的是将逻辑移动到beforeValidate
方法中,该方法与会话刷新行为无关。有一张门票可以添加afterValidate
,这更符合您的要求(但它还没有)。
但是,在这种情况下,最好只是反转极性并进行服务更新/保存新部件并解析并添加螺钉,而不是尝试将逻辑放入域对象。