Hibernate在级联上删除对象

时间:2010-09-15 07:30:38

标签: java hibernate orm cascading-deletes

我对cascade =“delete”的工作原理感到困惑。我在City映射文件中按以下方式定义了映射:

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

类Client具有类City的外键。

所以当我跑:

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()方法?谢谢你的帮助。 最好的祝福, SASS。

2 个答案:

答案 0 :(得分:7)

  

我对cascade =“delete”如何工作(...)

感到有些困惑

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

  

所以当我跑(...)时,所有客户都应该被删除

采用 HQL查询字符串Session#delete(String)方法,执行它,迭代结果并在每个对象上调用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()某些时候(并且还会改进您的错误处理,即catch块中的rollback()

参考

答案 1 :(得分:0)

  1. 如果删除城市,则也会删除所有客户端。如果您删除了一个客户端,该城市将被单独留下。

  2. 无法使用HQL查询调用
  3. session.delete()。您必须将其传递给一个城市才能删除。

  4. 或者,您可以使用session.createSQLQuery()创建删除语句。这允许您一次删除许多城市。这种方法的缺点是你必须自己删除客户端刷新缓存(Hibernate不会试图理解你的查询可能意味着什么)。