Grails多对多关联并防止级联

Rev*_*nzo 3 grails many-to-many hibernate-cascade

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

Customer {
  static hasMany = [roles: Role]
}

Role {
  static hasMany = [customer: Customer]
  static belongsTo = Customer
}
Run Code Online (Sandbox Code Playgroud)

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

我补充说:

static mapping = {
  roles cascade: 'none'
}
Run Code Online (Sandbox Code Playgroud)

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

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

Bur*_*ith 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'
   }
}
Run Code Online (Sandbox Code Playgroud)

映射块配置生成的DDL,使其与您现在拥有的相同,因此您无需进行任何数据库更改.静态帮助程序方法不是必需的,但可以方便地隐藏授予和撤消角色的过程.

您需要更改代码.由于没有hasMany,你不能使用customer.addToRoles(...).而不是授予角色只需使用该create方法创建新的CustomerRole实例并撤消,使用该remove方法删除实例.

更新的Role类将是

class Role {
}
Run Code Online (Sandbox Code Playgroud)

并且更新的Customer类将是

class Customer {
   Set<Role> getRoles() {
      CustomerRole.findAllByUser(this).collect { it.role } as Set
   }
}
Run Code Online (Sandbox Code Playgroud)

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