3

したがって、お客様と役割の間には多対多の関係があり、次のように設定されます。

Customer {
  static hasMany = [roles: Role]
}

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

Roleオブジェクトには、名前と一連の権限のみがあります。ロールは直接変更されるだけなので、Customer->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を構成するため、現在のDDLと同じになるため、データベースを変更する必要はありません。静的ヘルパーメソッドは必須ではありませんが、役割の付与と取り消しのプロセスを隠すのに便利です。

コードを変更する必要があります。がhasManyないので使用できませんcustomer.addToRoles(...)。代わりに、ロールを付与するには、メソッドを使用して新しいCustomerRoleインスタンスを作成し、create取り消すには、メソッドを使用してインスタンスを削除しますremove

更新されたRoleクラスは次のようになります

class Role {
}

更新されたCustomerクラスは

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

これには、顧客に付与された役割にアクセスする簡単な方法が必要になるため、によって作成されたコレクションgetRoles()を模倣する便利な方法があります。roleshasMany

于 2010-11-03T20:20:36.330 に答える