Как использовать уникальное ограничение на несколько столбцов вместо создания составного ключа - PullRequest
2 голосов
/ 15 октября 2011

В новой системе, которую я запускаю, есть несколько доменов, которые просто объединяют таблицы для отношений «многие ко многим». Все они похожи на этот пример для Spring Security Core. В случае Spring Security сопоставляется «устаревшая» база данных, поэтому необходимо использовать композитный ключ.

У меня вопрос: возможно ли наложить уникальное ограничение на комбинацию полей вместо необходимости использовать составной ключ и, следовательно, для реализации функций get и других. Я был бы счастлив использовать идентификатор в качестве ключа, но мне нужно убедиться, что записи уникальны.

Другими словами, как я могу добавить уникальное ограничение для 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 Ответ

2 голосов
/ 15 октября 2011

Вы можете сделать это, если вам разрешено добавить новый столбец, который будет настоящим первичным ключом, например, автоинкремент или столбец на основе последовательности. Тогда добавление уникального ограничения будет простым:

class SecUserSecRole {

   SecUser secUser
   SecRole secRole

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

Но я сомневаюсь, что это вариант:)

Обратите внимание, что Grails 2.0 имеет поддержку Hibernate Bags, что решает проблемы производительности коллекции, которые обходятся этим подходом SecUserSecRole.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...