В моем приложении у меня есть типы 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 решает сделать следующее, закрывая транзакцию и промывку:
- Вставьте новое правило в базу данных. Отлично.
- Обновите другие поля ролей (а не коллекции). Пока все хорошо.
- Обновите существующие правила, даже если в них ничего не изменилось. Я могу жить с этим.
- Обновите существующие правила еще раз. Здесь вставка из журнала, включая автоматический комментарий:
/* delete one-to-many row Role.rules */ update ROLE_RULE set ROLE_ID=null where ROLE_ID=? and ROLE_RULE_ID=?
Конечно, все поля не являются нулевыми, и эта операция не срабатывает эффектно.
Может кто-нибудь попытаться объяснить, почему Hibernate сделает это??? И что еще более важно, как я могу обойти это frak?
EDIT. Я был так уверен, что это как-то связано с отображением, а затем мой босс по прихоти удалил equals()
и hashCode()
в обоих классах, воссоздал их, используя Затмение, и таинственно это решило проблему.
Мне все еще очень любопытно узнать о моем вопросе. Может ли кто-нибудь предположить, почему Hibernate сделает это?