【问题标题】:grails, hasMany, set and duplicatesgrails, hasMany, set and duplicates
【发布时间】:2014-02-03 18:30:06
【问题描述】:

grails 文档说默认情况下 hasMany 是一个集合。 我的域如下所示:

class Employee {
    String name;
    String empId;
    String password;
    String contactNumber;
    String emailId;

    static hasMany = [roles : Role]

    static belongsTo = [department : Department]

    static constraints = {
        contactNumber nullable : true
        emailId nullable : true
        empId unique : true
        roles nullable : true
        department nullable : true
    }

    static mapping = {
        sort name : "asc"
    }
}

//Role class
class Role {
    String role;
    String roleId;
}

控制器中的以下代码允许将重复条目添加到“角色”:

roleListToBeAdded.each { r ->
                        println "Trying to add ${r}"
                        try {
                            employee.addToRoles(r).save(flush:true)
                        } catch (Exception e) {
                            println "failed to add ${r}: ${e}"
                        }
                    }

为什么会这样?

注意:如果 roleListToBeAdded 有多个相同角色的条目(例如:如果请求 JSON 看起来像这样:{"rolesToBeAdded" : [{"role":33}, {"role ":33}}) 那么它不会添加两次,但是如果说角色 33 已经添加并且我使用角色:33 再次发出新请求,那么它会在 'employee_role' 表中添加一条记录。

【问题讨论】:

  • Role 类是什么样的,尤其是它的equalshashCode 实现?
  • 我已经编辑了帖子并包含了 Role 类。

标签: grails grails-orm


【解决方案1】:

您需要将适当的equalshashCode 添加到 Role 类,因为 Set 唯一性基于 Java 相等性而不是数据库标识。 equals 定义应基于数据(例如角色名称)而不是数据库 ID,因为“临时”实例(尚未保存的实例)具有空 ID。

【讨论】:

  • 谢谢@Ian Roberts,我会试试你的解决方案。
  • 这里是该方法的代码 boolean equals(other) { if (!(other instanceof Role)) { return false } other.role == role && other.roleId == roleId } int hashCode( ) { def builder = new org.apache.commons.lang.builder.HashCodeBuilder.HashCodeBuilder() builder.append role builder.append roleId builder.toHashCode() }
【解决方案2】:

我认为问题不仅在“Set”或“equals”或“hashcode”实现中,而且在 Role 类中。这个类

class Role {
    String role;
    String roleId;
}

在这个类中有两个 id:第一个是 'roleId' 但它不是主键。实际上,如果您希望 'roleId' 成为 PK,则必须将静态映射添加到 Role 类(关注此帖子 Stack Post, 10120708):

 class Role {
    String role;
    String roleId;
    static mapping = {
       id column: 'roleId', type: 'varchar'
    }
 }

如果未设置此映射,则会有一个隐式 PK 定义为“id”(第二个 :))。如果您看到 grails 框架创建的表读取“角色”类,您将看到如下内容:

TableName Role
id(This is PK)           role           roleId
---                      ---            ---

这就是为什么 equals/hashcode 默认方法似乎不起作用的原因,它们在隐式 id 之间进行比较,而不是在 roleId 之间进行比较。

再见

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多