如何在多列上使用唯一约束而不是创建复合键

时间:2011-10-15 03:51:37

标签: grails many-to-many constraints unique-constraint

我刚开始使用的新系统有几个域,它们只是用于多对多关系的连接表。它们都像Spring Security Core的这个例子。在Spring Security的情况下,正在映射“遗留”数据库,因此使用复合键是必要的。

我的问题是,是否可以对字段组合设置唯一约束,而不必使用复合键,因此必须实现get和其他功能。我很乐意使用id作为密钥,但我确实需要确保记录是唯一的。

换句话说,如何在secUser + secRole上添加唯一约束,而不是在以下域中创建复合键?

class SecUserSecRole implements Serializable {

    SecUser secUser
    SecRole secRole

    boolean equals(other) {
        if (!(other instanceof SecUserSecRole)) {
            return false
        }

        other.secUser?.id == secUser?.id &&
            other.secRole?.id == secRole?.id
    }

    int hashCode() {
        def builder = new HashCodeBuilder()
        if (secUser) builder.append(secUser.id)
        if (secRole) builder.append(secRole.id)
        builder.toHashCode()
    }

    static SecUserSecRole get(long secUserId, long secRoleId) {
        find 'from SecUserSecRole where secUser.id=:secUserId and secRole.id=:secRoleId',
            [secUserId: secUserId, secRoleId: secRoleId]
    }

    static SecUserSecRole create(SecUser secUser, SecRole secRole, boolean flush = false) {
        new SecUserSecRole(secUser: secUser, secRole: secRole).save(flush: flush, insert: true)
    }

    static boolean remove(SecUser secUser, SecRole secRole, boolean flush = false) {
        SecUserSecRole instance = SecUserSecRole.findBySecUserAndSecRole(secUser, secRole)
        if (!instance) {
            return false
        }

        instance.delete(flush: flush)
        true
    }

    static void removeAll(SecUser secUser) {
        executeUpdate 'DELETE FROM SecUserSecRole WHERE secUser=:secUser', [secUser: secUser]
    }

    static void removeAll(SecRole secRole) {
        executeUpdate 'DELETE FROM SecUserSecRole WHERE secRole=:secRole', [secRole: secRole]
    }

    static mapping = {
        id composite: ['secRole', 'secUser']
        version false
    }
}

1 个答案:

答案 0 :(得分:2)

如果您允许添加一个真正主键的新列,例如,您可以这样做。自动增量或基于序列的列。然后添加唯一约束很简单:

class SecUserSecRole {

   SecUser secUser
   SecRole secRole

   static constraints = {
      secUser(unique:'secRole')
   }
}

但我怀疑这是一个选择:)

请注意,Grails 2.0支持Hibernate Bags,它解决了此SecUserSecRole方法解决的集合性能问题。