如下所示:
hql = " update Table1 set prob1=null where id=:id1; " + " delete from Table2 where id =:id2 "; ... query.executeUpdate();
在同一个executeUpdate调用中,我想更新Table1中的记录,并从表2中删除记录.
那可能吗?
解决方法
从我过去的经验来看,HQL的批处理功能在现实生活中很少有用.这可能听起来很奇怪,某些东西在sql JDBC中有用,但不在HQL中.我会尽力解释.
通常当我们使用Hibernate(或其他类似的ORM)工作时,我们对实体工作. Hibernate将负责将实体的状态与DB进行同步,这是JDBC批处理可以帮助提高性能的大多数情况.但是,在Hibernate中,我们不会通过批量更新查询来更改单个实体的状态.
给出一个例子,在伪代码中:
在JDBC中,您可以执行以下操作(我正在尝试模拟您在exmaple中显示的内容):
List<Order> orders = findOrderByUserId(userName); for (Order order: orders) { if (order outstanding quantity is 0) { dbConn.addBatch("update ORDER set STATE='C' where ID=:id",order.id); } else if (order is after expriation time) { dbConn.addBatch("delete ORDER where ID=:id",order.id); } } dbConn.executeBatch();
从JDBC逻辑到Hibernate的真实翻译可能会给你这样的东西:
List<Order> orders = findOrderByUserId(userName); for (Order order: orders) { if (order outstanding quantity is 0) { q = session.createQuery("update Order set state='C' where id=:id"); q.setParameter("id",order.id); q.executeUpdate(); } else if (order is after expriation time) { q = session.createQuery("delete Order where id=:id"); q.setParameter("id",order.id); q.executeUpdate(); } }
我怀疑你认为你需要批处理功能,因为你正在做类似的事情(根据你的例子,你使用批量更新单个记录).但是在Hibernate / JPA中不应该如何做
(实际上最好是通过存储库包装持久层访问,这里我只是简化了图片)
List<Order> orders = findOrderByUserId(userName); for (Order order: orders) { if (order.anyOutstanding()) { order.complete(); // which internally update the state } else if (order.expired) { session.delete(order); } } session.flush(); // or you may simply leave it to flush automatically before txn commit
通过这样做,Hibernate足够智能地检测更改/删除/插入的实体,并利用JDBC批处理在flush()中执行DB CUD操作.更重要的是,这是ORM的全部目的:我们希望提供行为丰富的实体来处理,实体的内部状态变化可以“透明地”反映在持久存储中.
HQL批量更新目的在于其他用途,这就像DB的一个批量更新影响大量记录,例如:
q = session.createQuery("update Order set state='C' " + " where user.id=:user_id " + " and outstandingQty = 0 and state != 'C' "); q.setParameter("user_id",userId); q.executeUpdate();
在这种使用情况下很少需要执行大量查询,因此,DB往返的开销是微不足道的,因此对批量更新查询的批处理支持的益处很少.
我不能忽略有些情况,您真的需要发布大量的更新查询,这不适合通过有意义的实体行为来完成.在这种情况下,您可能需要重新考虑Hibernate是否是正确使用的工具.您可以考虑在这种用例中使用纯JDBC,以便控制如何发出查询.