3

因此,我们在客户和角色之间建立了多对多关系,设置为:

Customer {
  static hasMany = [roles: Role]
}

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

Role 对象只有一个名称和一组权限。我们不想从 Customer -> Role 级联保存,因为 Role 只能直接修改。

我补充说:

static mapping = {
  roles cascade: 'none'
}

但是,每当我创建客户时,角色表也会更新。没有任何变化,只是版本号增加了。

我是否遗漏了需要设置的其他内容...在 Grails 中设置了多少对多关系和级联是否存在错误...或者是否有其他方法可以防止角色每次都被更新?

4

1 回答 1

5

我通常将连接表映射为域类以避免此问题和其他问题(集合加载性能、乐观锁定错误等)。这涉及删除hasManybelongsTo创建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(...)。而不是授予角色,只需使用该方法创建一个新的 CustomerRole 实例,create然后使用该方法撤消、删除该实例remove

更新的角色类将是

class Role {
}

更新后的 Customer 类将是

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

这有一个方便的方法getRoles(),它模仿了roles为您创建的集合,hasMany因为您仍然需要一种简单的方法来访问客户的授予角色。

于 2010-11-03T20:20:36.330 回答