【问题标题】:grails (gorm) set contains and persists duplicatesgrails (gorm) 集包含并保留重复项
【发布时间】:2013-01-10 22:07:31
【问题描述】:

我现在不太明白我的代码中发生了什么。据我了解,groovy 集不包含重复项。但是,我在一组中看到重复项,并且还看到重复项保存到数据库中。虽然从数据库中检索时,重复项不在集合中。

我有两个类(为简洁起见删除了一些属性):

class EntityType {
    static hasMany = [attributes: Attribute]
}

class Attribute {
    String keyname
}

在我的服务中,我传入一个属性的 jsonarray,这些属性使用 type.addToAttributes(attr) 添加到 EntityType。如果我多次执行相同的调用,则会将重复项添加到 Set。并且在持久化时,重复项会被持久化。但是,当我从数据库中检索 Set 时,检索到的 Set 没有任何重复。所以最终的结果是除了用不必要的数据填充数据库表之外,它似乎没有任何伤害。

我缺少关于 Set 的什么?

编辑:这是我刚刚注意到的一些奇怪的事情。不会为所有属性创建重复项。仅创建 n-1 个副本。遍历属性 jsonarry 时,第一个属性不重复,但之后的每个属性都是重复的。所以如果我的数组是 {a:1,b:2,c:3} 它只会创建 b 和 c 的副本。

【问题讨论】:

  • 如何创建attr 实例?看起来您有多个 Attribute 实例具有相同的 keyname ...
  • 我有一个属性服务,它返回现有的同名属性或创建一个新的同名属性。奇怪的是,新的属性并没有被创建和持久化,只有新的关系(EntityType-Attribute)是用现有的属性创建的。

标签: grails grails-orm


【解决方案1】:

我想通了。我最终不得不重写 int hashCode()boolean equals(Object o) 方法:

@Override
int hashCode() {
    return keyname.hashCode() + id.hashCode()
}

@Override
boolean equals(Object o) {
    Attribute other = o as Attribute
    return keyname.equals(other.keyname) && id.equals(other.id)
}

虽然我不太喜欢这样,因为如果我添加新属性,它会强制我更新这些方法,但它现在可以工作。

【讨论】:

  • 我在使用 TreeSet 和 LinkedHashSet 的 Grails 中遇到了同样的问题,但是在你的 equals 和 hashCode 方法中使用 id 违反了合同——hashCode 和 equals 应该基于生命中的不可变值的集合。见onjava.com/pub/a/onjava/2006/09/13/…。我仍在试图弄清楚如何在我的集合中避免重复引用(字面意思是,hashCode、equals、compareTo 甚至 JVM 内存引用都表示它们是相同的),但我认为不是这样。
  • 另外,根据 id 会告诉你,与已保存属性具有相同键名的未保存属性不等于已保存属性。这可能导致重复项实际上被持久保存在数据库中。
【解决方案2】:

我同意 aiolos 的观点,最明显的原因是您有多个同名的属性。

您可以防止这种情况使键名唯一

class Attribute {
    String keyname

    static constraints = {
        keyname unique:true
    }
}

【讨论】:

  • 不是多个同名的属性,至少在数据库中没有。当关系行被持久化时,它们是真正的重复行。 IE。实体类型 1 和属性 3 的几行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
  • 2019-02-12
  • 1970-01-01
  • 2022-11-15
  • 2013-07-10
  • 2016-01-06
  • 2022-01-23
相关资源
最近更新 更多