Hibernate在级联上删除对象

sas*_*ass 4 java orm hibernate 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>
Run Code Online (Sandbox Code Playgroud)

类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();
   }
}
Run Code Online (Sandbox Code Playgroud)

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

Pas*_*ent 7

关于cascade ="delete"是如何工作的,我有点困惑(...)

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

所以,当我运行(...)时,所有客户端也应该被删除

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()
Run Code Online (Sandbox Code Playgroud)

但请注意,批量删除有以下限制:

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

因此,通过批量删除,您必须删除Client之前的City.但表现要好得多.

PS:你需要commit()在某个时候(并且还改进你的错误处理,即rollback()在catch块中)

参考