私のアプリには、これらの Hibernate マップ型があります (一般的なケース):
class RoleRule {
private Role role;
private PermissionAwareEntity entity; // hibernate-mapped entity for which permission is granted
private PermissionType permissionType; // enum
@ManyToOne
@JoinColumn(name = "ROLE_ID")
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
class Role {
private Set<RoleRule> rules = new HashSet<RoleRule>(0);
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="ROLE_ID")
public Set<RoleRule> getRules() {
return rules;
}
public void setRules(Set<RoleRule> rules) {
this.rules = rules;
}
}
すべてのクラスにはequals() & hashCode()
オーバーライドがあります。
私のアプリケーションでは、ロールの微調整が可能で (システム管理者のみ、心配しないでください)、他のフィールドの中でも、新しいロール ルールの作成が可能です。新しいルールが作成されると、新しいRoleRule
オブジェクトを作成してロールのフィールドに挿入しようとしますrules
。session.update(role)
データベースに変更を適用するために呼び出します。
醜い部分が来ます... Hibernateは、トランザクションを閉じてフラッシュするときに次のことを行うことにしました:
- 新しいルールをデータベースに挿入します。優秀な。
- 他の役割フィールド (コレクションではない) を更新します。ここまでは順調ですね。
- 何も変更されていない場合でも、既存のルールを更新します。私はこれで暮らすことができます。
- 既存のルールを再度更新します。自動コメントを含むログからの貼り付けは次のとおりです。
/* 1 対多の行 Role.rules を削除します */ update ROLE_RULE set ROLE_ID=null どこで ROLE_ID=? および ROLE_RULE_ID=?
もちろん、すべてのフィールドは非 null であり、この操作は見事に失敗します。
Hibernateがこれを行う理由を誰か説明できますか??? そしてさらに重要なのは、どうすればこれを回避できるのでしょうか???
編集:マッピングに関係があると確信していたので、上司が気まぐれに削除しequals()
、hashCode()
両方のクラスでEclipseを使用してそれらを再作成し、不思議なことにこれで問題が解決しました。
私はまだ私の質問について非常に興味があります。Hibernateがこれを行う理由を誰かが提案できますか?