2012-06-26 2 views
0

У меня есть ItemList класса, содержащего набор Items отображенных так:Hibernate партии вставки в однонаправленные коллекции один-ко-многим

<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> 

Это однонаправленная ассоциация. Мне нужно вставить 1000s из Items в ItemList. Использование спящего режима док на пакетных вставок, у меня есть что-то вроде этого:

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. Затем все 30 элементов обновляются с помощью PID элемента списка.

  1. Как я могу избежать увеличения версии ItemList после каждой партии?
  2. Как я могу избежать 30 обновлений?

ответ

0
  1. К сожалению, не могу вам помочь с этим (но почему вы заботитесь?).

  2. Вы имеете в виду обновление каждые 30 предметов? Вы тоже не хотите ... если только вы не захотите рисковать нехваткой памяти, так как все тысячи Item s хранятся в кеше уровня сеанса.

  3. Это работает, потому что, как и documentation из Session.flush() состояний:

Промывка является процессом синхронизации основного стойких магазина с persistable состояния, состоявшимся в памяти.

Итак, после промывки вы закончили и хорошо с последними 30 пунктами, они находятся на стороне БД. Однако, это не значит, что они совершено. БД знает, что вы находитесь в середине транзакции, которая еще не была выполнена.

EDIT

Может быть, теперь я понимаю, почему версия увеличивается после каждого flush. Я размышляю здесь. Hibernate использует столбец version, чтобы убедиться, что с момента начала транзакции никакая другая транзакция не изменила объект, который был изменен текущей транзакцией. Но эта проверка выполняется исключительно от имени Hibernate, не используя для этого никакой функциональности DB. Я предполагаю, что это верно, потому что DDL таблиц версий показывает, что столбец version является простым int (это также имеет смысл, поскольку Hibernate является API-интерфейсом для нескольких DB-поставщиков, но OTOH они могут иметь специальные инструменты для каждого поставщика). Итак, перед тем, как промыть, Hibernate имеет последний шанс проверить, что сбрасываемые объекты не являются устаревшими данными. После промывки эти обновленные объекты больше не помечены для обновления, поэтому будущие сбросы даже в той же транзакции не будут запускать событие проверки версии.

+0

(1) Потому что все вставки - это только одна операция, и версия должна отражать это. (2) После того, как 30 элементов вставлены, запускаются 30 операторов UPDATE. Я пытаюсь их избежать. (3) Мой последний вопрос был неясным, но я думаю, что понял это. – takteek

+0

(1) Я отредактировал ответ, чтобы он попытался объяснить, почему это невозможно. (2) Я удивлен этим ... У меня нет ответа на это, и я не понимаю, почему Hibernate не мог автоматически оптимизировать эту оптимизацию. (3) отлично. – yair

+0

и (1) 'version' не должен отражать это, поскольку он предназначен для оптимистического контроля параллельности блокировки. Таким образом, это не обязательно отражает _transactions_. – yair

Смежные вопросы