JPA – 批量/批量更新 – 更好的方法是什么?

我发现JPA不支持以下更新:

Update Person p set p.name = :name_1 where p.id = :id_1, p.name = :name_2 where p.id = :id_2, p.name = :name_3 where p.id = :id_3 .... // It could go on, depending on the size of the input. Could be in 100s 

所以我有两个选择:

选项1:

 Query q = em.createQuery("Update Person p set p.name = :name where p.id = :id"); For ( int x=0; PersonsList.length; x++ ) { // add name and id parameters em.executeUpdate(); } 

问题:

  1. 这是批量更新所需要的吗? 还有什么需要补充的吗? 我设置了hibernate.jdbc.batch_size", "20"
  2. 默认情况下是否在此处启用了乐观锁定? (虽然我的实体中没有@Version)
  3. 如果不是@Version,我需要做什么才能执行乐观锁定?

选项2:

使用Select Case语法或Criteria API构造一个单一查询

问题:

  1. 批量配置是否仍然在这里发生? (在一个大的查询中)
  2. 在性能方面,这比第一种方法更好吗?
  3. 这两种选择中推荐的方法是什么? 还有其他更好的方法?

如果您打算使用批处理,请参阅hibernate文档的这一章

batch_size更多的是内存优化而不是查询优化,查询保持不变,但您也可以通过充分利用内存来最小化往返。 你需要刷新()和清除()每次N次取决于batch_size的设置。

但仍然。 。

1语句中的更新比多语句中的更新快得多,因此如果您:

  • 可以简单地循环并在SQL中执行此操作
  • 无需级联更新到其他实体
  • 更新多个值时,您确实需要更快的性能
  • 并且不需要其他HQL优势,例如防止sql注入的预处理语句

然后你可以考虑只创建本机查询而不是hql。

在您的问题标题中,您提到了批量更新和删除,但实际上您需要这次批处理。

如果要更新/删除所有匹配相同过滤条件的行,则需要批量更新和删除,这些行可以在WHERE子句中表示。

在这里,您需要JDBC批量更新。 如本文所述 ,您需要设置以下配置属性:

  

如果你这样做,你可以简单地更新实体,Hibernate会为你批量UPDATE语句。

选项1不是很有用,因为它将生成无法批处理的N UPDATE语句。

选项2不是很有用,因为它会生成一个非常复杂的查询,其执行计划可能比在简单的批处理UPDATE语句中执行所有内容更复杂。

所以,这样做:

  1. 使用分页获取实体
  2. 使用Hibernate更新它们,让它为您进行批量更新。

如果您有许多此类实体,请按照本文中的说明使用分页。

您可以更新对象列表,而无需遍历所有集合。

 List demo = Arrays.asList(1,2,3,4); final String update = "UPDATE User u SET u.enabled = true WHERE u.id IN (?1)"; return super.getEntityManager() .createQuery(update) .setParameter(1, ids) .executeUpdate();