0

我有ItemList一个包含一组这样的Items映射的类:

<class name="ItemList">
   <id name="PID" column="PID">
      <generator class="uuid" />
   </id>
   <version name="Version" />
   <set cascaed="save-update" name="Items">
      <key column="itemlist_id" />
      <one-to-many class="Item" />
   </set>
</class>

<class name="Item">
   <id name="PID" column="PID">
      <generator class="uuid" />
   </id>
   ...
</class>

这是一个单向关联。我需要批量插入 1000 个ItemsItemList. 在批量插入上使用休眠文档,我有这样的事情:

ItemList itemList = ...

int i = 0;
for (Item item : someItems) {
    // .. some processing..

    itemList.getItems().add(item);

    if (++i % 30 == 0) {
       session.update(itemList);
       session.flush();
       session.clear();
    }
}

显然存在一些问题。每次刷新时,插入 30 个项目。然后更新 ItemList 的版本。然后用 ItemList 的 PID 更新所有 30 个 Item。

  1. 如何避免在每批之后增加 ItemList 版本?
  2. 如何避免 30 次更新?
4

1 回答 1

0
  1. 对不起,不能帮助你(但你为什么在乎?)。

  2. 你的意思是每30个项目更新一次?您也不想...除非您愿意冒内存不足的风险,因为所有数千个Items 都存储在会话级缓存中。

  3. 它之所以有效,是因为作为状态的文档Session.flush()

刷新是将底层持久存储与内存中保存的持久状态同步的过程。

因此,在冲洗完最后 30 个项目之后,它们就在 DB 端了。然而,这并不意味着他们承诺。数据库知道您正处于尚未提交的事务中间。

编辑

也许我现在意识到为什么版本在每个flush. 我在这里推测。Hibernate 使用该version列来验证,因为事务已经开始,没有其他事务更改了当前事务修改的实体。但此验证仅代表 Hibernate 完成,不使用任何数据库固有功能。我认为这是真的,因为版本表的 DDL 显示该version列是普通的int(这也是有道理的,因为 Hibernate 是一个跨 DB 供应商的 API,但 OTOH 他们可以为每个供应商提供特定的工具)。因此,就在刷新之前,Hibernate 有最后一次机会来验证刷新的实体不是陈旧的数据。刷新后,这些更新的实体不再被标记为更新,因此未来的刷新,即使在同一个事务中,也不会触发版本验证事件。

于 2012-06-26T00:52:49.670 回答