Hibernate批量插入单向一对多集合

时间:2012-06-26 00:32:25

标签: hibernate hibernate-mapping batch-processing

我有一个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>

这是单向关联。我需要将Items的1000个批量插入ItemList。在批量插入上使用hibernate doc,我有类似的东西:

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个项目。

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

1 个答案:

答案 0 :(得分:0)

  1. 抱歉,对此无能为力(但为什么要关心?)。

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

  3. 这是有效的,因为Session.flush()documentation状态:

  4.   

    Flushing 是同步底层持久性的过程   持久存在的商店。

    因此,在冲洗完毕后你已经完成了最后30项,他们就在数据库方面。 然而,并不意味着他们已提交。数据库知道您正处于尚未提交的事务中间。

    修改

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