删除一对多关系中的子项会引发ObjectDeletedException [英] Delete child in one-to-many relation throws ObjectDeletedException

查看:138
本文介绍了删除一对多关系中的子项会引发ObjectDeletedException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是不明白为什么Hibernate会抛出标题中提到的异常。我可能不了解Hibernate背后的状态管理理念。



我有以下情况:

组织与员工之间的一对多关系

Organization.hmb.xml

 < set name =employeesinverse =truecascade =save-update> 
< key column =organization_id/>
<一对多等级=雇员/>
< / set>

Employee.hbm.xml

 <多对一名称=组织class =Organizationcolumn =organization_id/> 

我使用带有Services和DAO的标准Spring / Hibernate应用程序体系结构,其中DAO扩展了HibernateDaoSupport类并使用服务用于会话管理的HibernateTemplate类。



当我在这种情况下尝试删除Employee时...

  Employee e = employeeService.read(1); 

//编辑:重要! EmployeeService中的删除操作是(@)事务性
employeeService.delete(e); //这个调用只是委托执行到employeeDao.delete

编辑:I起初没有提到在服务层的删除操作是事务性的,这似乎是重要的信息(继续阅读)!



Hibernate抛出...

  ObjectDeletedException:被删除的对象会通过级联重新保存... 

删除EmployeeService中的操作看起来像...

  @Transactional public void delete(Employee emp){
Employee e = employeeDao.read(emp.getId());
if(e == null)
throw NoSuchOrganizationException();

/ * ..几个while -s删除员工是
而不是关系所有者的关系... * /

employeeDao.delete(e) ;

方案(它们不相关): < br>
1. 当我从Organization.hbm.xml中的关系映射中删除cascade =save-update时,一切工作正常
2. 当我从delete方法中删除@Transactional 注释时,一切正常。

3. 当我删除child(Employee)父母(组织)的孩子列表,然后执行删除,一切正常。


$ b

问题



为什么Hibernate在乎父级中的级联

他认为级联的执行点在哪里组织对象
为什么他不能删除员工(孩子)DELETE FROM ...就是这样。此外,员工是关系的所有者,对他执行的操作应该自己管理关系。 无论如何他想在所提及的场景中调用组织对象的任何操作?我只是不明白。

解决方案

您可能会遗漏的是,Hibernate会自动为已经加载并存在于Session中的实体维护状态,这意味着它会不管你是否显式调用update()方法,都要坚持对它们进行的任何更改无关紧要。考虑到你的情况,如果你已经加载了 Organization 和它的 employees 集合,现在正试图删除其中一个员工,Hibernate告诉你(通过抛出 ObjectDeletedException )它将重新保存已删除的员工,因为您已经声明保存或更新应该是保存组织从组织到部门级别的员工级联。



处理这种情况的正确方法是从组织的 employees b

编辑(基于更新后的消息队列) ):

组织 拥有员工集合。 Cascade始终遵循关联 - 您已在 Organization 一侧声明它,因此更改(save / update)会传播到 Employee 级别。只要特定的 Employee 实例是任何组织 employees 集合的成员c $ c $>在会话中存在的实体,当会话被刷新/关闭时,它将被保存(或重新保存,因此抛出异常)。



事实关联从 Employee 一侧映射(例如 organization_id 列存在于 Employee 表)在这里是不相关的;它可能已经通过连接表映射了相同的结果。 Hibernate通过会话维护状态,当你试图从 Organization.employees 中删除​​ Employee 时, '给Hibernate冲突的指令(因为它仍然活着 - 必须保存 - 在一个地方,但在另一个地方被删除),因此是例外。


I just don't understand why Hibernate throws exception mentioned in title. I probably don't understand state management idea behind Hibernate.

I have following situation:

One-to-many relation between Organization and Employee

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" />

I use standard Spring/Hibernate app architecture with Services and DAOs, where DAOs extend HibernateDaoSupport class and use services of HibernateTemplate class for Session management.

When I try to delete Employee in this scenario...

Employee e=employeeService.read(1); 

//EDIT: Important! delete operation in EmployeeService is (@)transactional  
employeeService.delete(e); //this call just delegate execution to employeeDao.delete

EDIT: I did not mention at first that delete operation in Service layer is transactional which seems to be important info (keep reading)!

Hibernate throws...

 ObjectDeletedException: deleted object would be re-saved by cascade...

Delete operation in EmployeeService looks like...

  @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);  
}

Scenarios (they are not related):
1. When i remove cascade="save-update" from relation mapping to Employee(s) in Organization.hbm.xml, everything works fine.
2. When i remove @Transactional annotation from delete method everything works fine.
3. When i delete child(Employee) from parent(Organization) list of children, and then execute delete, everything works fine.

Question:

Why Hibernate cares at all about cascade in parent class?
Where is the point in execution at which he considers cascade on Organization object? Why he just can't delete Employee(Child) with DELETE FROM... and that's it. Besides, Employee is the owner of relationship and operations executed on him should manage relation itself. When he thought to call any operation on Organization object in mentioned scenario anyway? I just don't get it.

解决方案

What you may be missing is that Hibernate automatically maintains state for entities that have been loaded and exist in Session, meaning it will persist any changes made to them irregardless of whether you explicitly invoke "update()" method.

Considering your scenario, if you have loaded Organization and its employees set and are now trying to delete one of those employees, Hibernate is telling you (by throwing ObjectDeletedException) that it will re-save deleted employee when it will save Organization because you've declared that saving or updating should be cascaded from organization down to employees in its set.

The proper way to handle this would be to remove said employee from organization's employees set before deleting it thus preventing cascaded re-save.

Edit (based on updated question):

Organization owns collection of employees. Cascade always follows the association - you've declared it on Organization side, so changes (save / update) are propagated down to Employee level. As long as particular Employee instance is a member of employees collection of any Organization entity that lives in session, it will be saved (or re-saved, so Exception is thrown) when session is flushed / closed.

The fact that association is mapped from Employee side (e.g. organization_id column resides in Employee table) is irrelevant here; it could have been mapped via join table with the same results. Hibernate maintains "state" via session and when you're trying to delete Employee without removing it from Organization.employees you're giving Hibernate conflicting instructions (since it's still alive - and has to be saved - in one place but is deleted in the other), hence the exception.

这篇关于删除一对多关系中的子项会引发ObjectDeletedException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆