多くの多くの関連性とカスケードを防ぐための聖杯
-
28-09-2019 - |
質問
したがって、私たちは顧客と役割の間に多くの関係があり、次のように設定されています。
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(...)
. 。代わりに、役割を付与するために、 create
方法と取り消しするには、を使用してインスタンスを削除します remove
方法。
更新されたロールクラスは次のとおりです
class Role {
}
そして、更新された顧客クラスはそうでしょう
class Customer {
Set<Role> getRoles() {
CustomerRole.findAllByUser(this).collect { it.role } as Set
}
}
これには便利な方法があります getRoles()
これを模倣します roles
あなたのために作成されたコレクション hasMany
顧客の付与された役割に簡単にアクセスする簡単な方法が必要になるためです。