0

我正在使用分配了 id 生成器的域类构建一个 grails 应用程序(也就是说,它们不会自动生成)。假设我有一个域类 Parentstatic hasMany = [children: Child]和域类 Child。

我正在尝试使用 查找 Parent 的实例Parent.findWhere(propertyMap),但收到NonUniqueObjectException指示已经有一个与此会话关联的 Child 实例,其 id 为 0。我的 propertyMap 不包含 id 的条目。

现在,每当我尝试在会话中保存一个类的两个实例而不设置它们的 id 时,我都习惯于得到这个错误。因为 id 不是自动生成的,所以它们默认为零,这允许保存第一个,第二个抛出错误,因为 id 是第一个的副本。令我惊讶的是,我试图找到一个实例,而不是保存一个......有谁知道可能导致这种行为的原因以及我如何在使用我的属性图进行搜索的同时绕过它?

4

2 回答 2

1

事实证明,这是一个时髦的语法糖问题。我在打电话 findWhere like

Parent.findWhere([ firstProperty: "firstValue", secondProperty: "SecondValue" ])

但显然我应该使用

Parent.findWhere( firstProperty: "firstValue", secondProperty: "SecondValue" )

(注意没有方括号)。我不知道为什么这会有所作为,但 findWhere 现在按预期工作。任何可能知道它为什么会这样表现的人都会加分。

于 2012-07-11T16:42:27.307 回答
0

好吧,如您所知,Hibernate 有一个强大的约束,即您不能在会话中拥有 2 个表示相同 id 的对象。您可能没有注意到的是,无论是在save()操作还是更新甚至是动态查询中:如果在同一个 Hibernate Session 中有 2 个具有相同 id 的对象,Hibernate 都会引发类似的异常。确保在您的会话中有另一个与该对象类似的对象。

这里说:

如果您使用 GORM 以任何方式检索域实例,例如通过 get() 方法或任何类型的查询,那么该对象将自动与会话关联。

会话中可能有一个子对象引用了父对象(还没有 id)。除了在您的父对象进入会话之前提供父对象 ID 或避免将引用父对象的子对象保存到会话之外,我没有看到其他优雅的方法。其他方法是evict()在您的对象上使用,例如:session.evict(object). 但这不是一件好事。

干杯!

于 2012-07-03T19:56:28.117 回答