Граальс Многие для многих ассоциаций и предотвращения каскада

StackOverflow https://stackoverflow.com/questions/4088810

Вопрос

Итак, у нас есть многозначные отношения между клиентом и ролью, созданные как:

Customer {
  static hasMany = [roles: Role]
}

Role {
  static hasMany = [customer: Customer]
  static belongsTo = Customer
}

Объект ролей имеет только имя и набор разрешений. Мы не хотим каскад экономит от клиента -> роли, как роль, как роль должна быть только изменена напрямую.

Я добавил:

static mapping = {
  roles cascade: 'none'
}

Но всякий раз, когда я создаю клиента, таблита роли также обновляется. Ничто не изменяется, за исключением того, что номер версии увеличивается.

Я упучаю что-то еще, что нужно установить ... Есть ли ошибка с тем, как многие ко многим отношениям и каскадам устанавливаются в границах ... Или есть какой-то другой способ, которым я могу предотвратить обновление ролей каждый раз?

Это было полезно?

Решение

Я обычно сопоставляю таблицу присоединения в качестве класса домена, чтобы избежать этой проблемы и других (производительность загрузки сбора, оптимистичные ошибки блокировки и т. Д.) Это включает в себя удаление hasMany и belongsTo и создание А. CustomerRole Класс домена:

import org.apache.commons.lang.builder.HashCodeBuilder

class CustomerRole implements Serializable {

   Customer customer
   Role role

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

      other.customer?.id == customer?.id &&
         other.role?.id == role?.id
   }

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

   static CustomerRole get(long customerId, long roleId) {
      find 'from CustomerRole where customer.id=:customerId and role.id=:roleId',
         [customerId: customerId, roleId: roleId]
   }

   static CustomerRole create(Customer customer, Role role, boolean flush = false) {
      new CustomerRole(customer: customer, role: role).save(flush: flush, insert: true)
   }

   static boolean remove(Customer customer, Role role, boolean flush = false) {
      CustomerRole instance = CustomerRole.findByCustomerAndRole(customer, role)
      instance ? instance.delete(flush: flush) : false
   }

   static void removeAll(Customer customer) {
      executeUpdate 'DELETE FROM CustomerRole WHERE customer=:customer', [customer: customer]
   }

   static void removeAll(Role role) {
      executeUpdate 'DELETE FROM CustomerRole WHERE role=:role', [role: role]
   }

   static mapping = {
      id composite: ['customer', 'role']
      version false
      table 'customer_roles'
   }
}

Блок сопоставления настраивает сгенерированный DDL, чтобы оно так же, как то, что у вас есть сейчас, поэтому вам не нужно будет внести какие-либо изменения базы данных. Методы статического помощника не требуются, но удобны скрывать процесс предоставления и отмены ролей.

Вам нужно будет изменить код код. Так как нет hasMany, вы не можете использовать customer.addToRoles(...). Отказ Вместо этого для предоставления роли просто создать новый экземпляр usserrole, используя create метод и отозвать, удалить экземпляр с использованием remove метод.

Обновленный ролевый класс будет

class Role {
}

и обновленный класс клиентов будет

class Customer {
   Set<Role> getRoles() {
      CustomerRole.findAllByUser(this).collect { it.role } as Set
   }
}

Это удобно метод getRoles() которые имитируют roles коллекция, созданная для вас hasMany Поскольку вам все равно понадобится простой способ доступа к предоставленным клиентам ролях.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top