圣杯:'integrity constraint violated'子记录何时保存在父记录之前



在父记录之前保存子记录时出现异常:

GrailsWrappedRuntimeException: ORA-02291:
integrity constraint (GRB.FKF8F6B734389E9766) violated -
parent key not found

代码:

class Child {
    Parent parent
    static constraints = {
        parent nullable: true
    }
}
class Parent {
    static hasMany = [ children: Child ]
}
def child = new Child()
child.save() // first save of Child
def parent = new Parent()
parent.save()
//session.flush() // the sudden flush
child.parent = parent
child.save()
// here is 'constraint violation' when transaction is committed

正如异常消息中所说,Child设置了父密钥Parent,但不知何故,Hibernate当时没有将该密钥视为现有行。。。

上面是我的代码中发生的事件的简化重建。请注意,这些操作是在代码的不同位置执行的(设计为相互分离)。不幸的是,这样一个缩小的代码工作得很好,并没有重现问题。。。此外,我以前从未遇到过这样的问题——我曾经在父记录之前保存子记录,反之亦然,没有任何问题。

我可以通过两种方式修复代码:

  • 评论Child的"第一次保存"(保存顺序很重要?!)
  • 或取消对会话刷新的注释

虽然我可以修复它,但我真的不想依赖于诸如保存顺序或突然的慌乱之类的事情。。。知道如何解决仍然有可靠代码的问题吗?

Grails 2.2.0、Hibernate 3.6、Oracle XE

您的异常可能是因为您在子表上没有可为null的parent约束的情况下进行了测试。如果没有null,那么在现有条目和新条目中就会有一个0或其他东西,因为DB正在发挥一些神奇的作用。GORM不会删除现有的FK,也不会向现有列添加可为null的约束。请尝试手动删除约束或删除整个列。仔细检查parent_id列上的可为null的约束。

关于你的问题,我建议你在父母身上添加孩子,而不是把孩子保存为孩子:

parent.addToChildren(child)

如果以前没有保存,这也会隐式保存子项。

最新更新