我只是不明白为什么Hibernate会抛出标题中提到的异常。我可能不了解Hibernate背后的状态管理理念。
我有以下情况:
组织与员工之间的一对多关系
Organization.hmb.xml
<set name="employees" inverse="true" cascade="save-update">
<key column="organization_id"/>
<one-to-many class="Employee"/>
</set>
Employee.hbm.xml
<many-to-one name="organization" class="Organization" column="organization_id" />
我使用标准的Spring / Hibernate应用程序架构与服务和DAO,其中DAO扩展HibernateDaoSupport类并使用HibernateTemplate类的服务进行会话管理。
当我尝试在此方案中删除员工时......
Employee e=employeeService.read(1);
//EDIT: Important! delete operation in EmployeeService is (@)transactional
employeeService.delete(e); //this call just delegate execution to employeeDao.delete
编辑:我最初没有提到服务层中的删除操作是事务性的,这似乎是重要信息(继续阅读)!
Hibernate抛出......
ObjectDeletedException: deleted object would be re-saved by cascade...
EmployeeService中的删除操作看起来像......
@Transactional public void delete(Employee emp){
Employee e=employeeDao.read(emp.getId());
if(e==null)
throw NoSuchOrganizationException();
/*...several while-s to delete relations where Employee is
not owner of relation... */
employeeDao.delete(e);
}
场景(它们无关):
1. 当我从Organization.hbm.xml中的关系映射到Employee(s)中删除cascade =“save-update”时,一切正常。
2. 当我从删除方法中删除@Transactional 注释时,一切正常
3. 当我从父(组织)子列表中删除子(Employee),然后执行删除时,一切正常。
问题:
为什么Hibernate关心父类中的级联?
他认为在组织对象上级联的执行点在哪里?
为什么他不能用DELETE FROM删除Employee(Child)......就是这样。此外,员工是关系的所有者,在他身上执行的操作应该管理关系本身。 当他想在所提到的场景中对组织对象进行任何操作时?我只是不明白。
答案 0 :(得分:11)
您可能缺少的是Hibernate会自动维护已加载并存在于Session中的实体的状态,这意味着它将继续对它们所做的任何更改 irregardless 是否显式调用“update”( )“方法。
考虑到您的方案,如果您已加载Organization
及其employees
设置并且现在正尝试删除其中一个员工,Hibernate会告诉您(通过抛出ObjectDeletedException
)它将在保存Organization
时重新保存已删除的员工,因为您已声明保存或更新应从组织级联到其集合中的员工。
处理此问题的正确方法是在删除之前从组织的employees
集中删除该员工,从而防止级联重新保存。
修改(根据更新的问题):
Organization
拥有员工集合。级联始终遵循关联 - 您已在Organization
侧声明它,因此更改(保存/更新)会向下传播到Employee
级别。只要特定Employee
实例是生成会话的任何employees
实体的Organization
集合的成员,它将在会话时保存(或重新保存,因此抛出异常)被冲洗/关闭。
关联从Employee
侧(例如organization_id
列位于Employee
表中)映射的事实在这里无关紧要;它可以通过连接表映射到相同的结果。 Hibernate通过会话维护“状态”,当你尝试删除Employee
而不从Organization.employees
删除它时,你会给出Hibernate冲突的指令(因为它仍然存在 - 并且必须保存 - 在一个放置但在另一个中被删除),因此例外。