我正在使用已分配了id生成器的域类构建grails应用程序(即,它们不会自动生成)。假设我有一个域类Parent static hasMany = [children: Child]
和域类Child。
我正在尝试使用Parent.findWhere(propertyMap)
找到Parent的实例,但是我得到一个 NonUniqueObjectException ,表明已经有一个与此会话关联的Child实例,其id为0.我的propertyMap是不包含id的条目。
现在,每当我尝试在会话中保存一个类的两个实例而不设置其ID时,我习惯于收到此错误。因为id不是自动生成的,所以它们默认为零,这允许第一个被保存,第二个抛出错误,因为id是第一个的副本。我在这里感到惊讶的是,我试图找到一个实例,而不是保存一个...有没有人知道可能导致这种行为的原因以及如何在使用我的属性映射进行搜索时绕过它?
答案 0 :(得分:1)
事实证明这是一个时髦的语法糖问题。我叫findWhere就像
Parent.findWhere([ firstProperty: "firstValue", secondProperty: "SecondValue" ])
但显然我应该使用
Parent.findWhere( firstProperty: "firstValue", secondProperty: "SecondValue" )
(注意缺少方括号)。我不知道为什么这会产生影响,但是现在找到了预期的效果。对于任何可能知道其行为的人来说,这是额外的一点。
答案 1 :(得分:0)
嗯,Hibernate有一个很强的约束,你不能在会话中拥有2个代表相同id的对象,如你所知。您可能没有注意到的事情是,无论是save()
操作还是更新,还是动态查询:如果在同一个Hibernate会话中有2个具有相同id的对象,Hibernate将引发异常喜欢那个。确保会话中存在另一个对象。
Here它说:
例如,如果您使用GORM以任何方式检索域实例 通过get()方法或任何类型的查询,然后对象是 自动与会话相关联。
在会话中可能有一个Child对象引用了Parent对象(它还没有id)。除了在进入会话之前给出父对象id或者避免将引用父对象的Child保存到会话之外,我没有看到其他优雅的方法。其他方法是在您的对象上使用evict()
,例如:session.evict(object)
。但这不是一件好事。
干杯!