2013-07-11 3 views
4

я обнаружил, что JPA не поддерживает следующие обновления:JPA - Batch/Bulk Update - Какой лучший подход?

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. Каков рекомендуемый подход из этих двух вариантов? Любой другой лучший подход?
+0

C'mon вы действительно хотите запустить объем в течение 3 рядов? bulk вызывает блокировку Intent на целевой таблице, и это нехорошо, просто запустите пакет 'em.begin()' и вызовите все DML и, наконец, 'em.commit();' –

+0

Нет. Его динамика. Я просто показал 3 в примере :-). Это может быть 100 секунд. –

+0

Это иждивенцы приятельницы, какая БД вы используете? и как часто вы хотите запускать такие запросы? но если вы спросите меня, я предпочитаю, чтобы DB предпочитал путь и запускал его параллельно с низким приоритетом. –

ответ

2

Если вы собираетесь использовать пакетный см this chapter of the hibernate documentation

batch_size больше для оптимизации памяти, чем оптимизации запросов, то запрос остается такой же, но вы также можете свести к минимуму туда и обратно в полной мере использовать ваш Память. вам необходимо очистить() и очистить() каждый N раз от значения параметра batch_size.

но все еще. ,

Обновление в 1 заявление гораздо быстрее, чем обновление при рассеянном заявлении, так что если вы:

  • Может просто петля и сделать это в SQL
  • Нет необходимости в каскаде, что обновление для других организаций
  • Вам действительно нужна намного более высокая производительность при обновлении нескольких значений
  • И не нужно другое преимущество HQL, как подготовленное заявление, которое предотвращает внедрение в SQL-код

Тогда вы можете рассмотреть возможность создания собственного запроса, кроме hql.

+0

Но, если я использую собственный запрос на обновление, не получаю ли я режим «пакетного обновления»? Мне сказали использовать пакетное обновление. Так что мне интересно, что это лучший способ сделать это –

+0

, как я сказал, batch_size - это всего лишь вопрос управления памятью, поэтому вы можете совершать десять тысяч строк в одном коммите без использования ** OutOfMemoryException **. поэтому, если ваш собственный запрос может делать то, что вам нужно, не имея OutOfMemoryException, вы можете использовать его, но если вы не используете HQL. Но у меня в SQL не будет проблемы с OutOfMemoryException, потому что спящий режим просто сохраняет ** сохраненные ** объекты в кеш-кеш-сессии. – Angga

1

В заголовке вопроса вы упомянули «Массовое обновление и удаление», но на этот раз вам действительно нужно дозировать.

Bulk Update and Delete необходимы, если вы хотите обновлять/удалять строки, которые соответствуют тем же критериям фильтрации, которые могут быть выражены в предложении WHERE.

Здесь вам нужны обновления JDBC. Как объяснялось в this article, вам необходимо установить следующую конфигурацию свойства:

<property name="hibernate.jdbc.batch_size" value="50"/> 

Если вы сделаете это, вы можете просто обновить объекты и Hibernate будет пакетные операторы UPDATE для вас.

Вариант 1 не очень полезен, поскольку он будет генерировать N операторов UPDATE, которые не могут быть загружены.

Вариант 2 не очень полезен либо потому, что он будет генерировать очень сложный запрос, чей план выполнения, вероятно, более сложный, чем выполнение всего в простой пакетной инструкции UPDATE.

Таким образом, сделать это следующим образом:

  1. Fetch все объекты
  2. обновить их с помощью Hibernate и дайте ему сделать обновление партии для вас.

Если у вас много таких объектов, используйте разбиение на страницы, как описано в this article.

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