私は通常、この問題やその他の問題(コレクションの読み込みパフォーマンス、楽観的ロックエラーなど)を回避するために、結合テーブルをドメインクラスとしてマップします。これには、ドメインクラスの削除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を構成するため、現在の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()
を模倣する便利な方法があります。roles
hasMany