一尘不染

Hibernate级联删除对象

hibernate

我对级联=“删除”的工作方式感到困惑。我在“城市”映射文件中以以下方式定义了映射:

<set inverse="true" name="client" cascade="delete">
  <key>
    <column name="id_name"/>
  </key>
    <one-to-many class="model.Client"/>
 </set>

类客户具有类城市的外键。

因此,当我运行时:

List object = null;
try {
   org.hibernate.Transaction tx = session.beginTransaction();
   try {
       session.delete("from City where row_id=" + row_id and table_id = " + table_id);
   } catch (Exception e) {
       e.printStackTrace();
   }
}

是否还应该删除所有客户端,还是必须以某种方式处理它?我是否将查询作为方法参数正确传递给会话的delete()方法?谢谢你的帮助。最好的问候,混蛋。


阅读 191

收藏
2020-06-20

共1个答案

一尘不染

我对cascade =“ delete”的工作方式有些困惑(…)

级联delete操作意味着,如果您delete是父母,则该操作将沿关联传播。因此,在您的情况下,删除City实体应传播到Client

因此,当我运行(…)时,也应该删除所有客户端

Session#delete(String)方法接受 HQL查询字符串 ,执行该 字符串
,遍历结果,并按Session#delete(Object)级联方式调用每个对象(因此,如果您的查询实际上是HQL查询,则客户端将被删除)。

但是此方法很旧,并且在Hibernate 3中已弃用(并移至“经典”Session界面),我并不建议这样做(它执行1 +N操作,删除大量结果效率很低)。

如果这是一个问题,请使用Hibernate提供的 批量删除 支持:

int deleteCount = session.createQuery("delete from Foo where bar = :bar") 
    .setParameter("bar", bar);
    .executeUpdate()

但是请注意,批量删除有一些限制:

  • 您不能使用别名。
  • 查询中没有内部联接(尽管您可以在where子句中使用子选择)。
  • 一个 批量删除不级联 (而不会照顾连接的表)。

因此,使用批量删除功能,您必须删除Client之前的City。但是性能要好得多。

PS:您需要commit()在某个时候进行(并改善错误处理,即rollback()在catch块中)

参考文献

2020-06-20