Подтвердить что ты не робот

Пакетные вставки с использованием JPA EntityManager

Можно ли использовать пакетные вставки с помощью JPA EntityManager. Я знаю, что нет прямого способа достичь этого, но должен быть какой-то способ достичь этого механизма.

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

Здесь код, который я использую в настоящее время для одиночных вставок

        @PersistenceContext(unitName = "testing")
        EntityManager eM;

        Query querys = this.eM.createNativeQuery(insertQuery);
        for (String s : someList) {
            //setting parameters
            querys.executeUpdate();
        }

Спасибо заранее.

4b9b3361

Ответ 1

Можно выполнять пакетную запись с использованием JPA, но она сильно зависит от конкретной реализации вашего провайдера персистентности, базы данных и драйвера JDBC. Например, в статье объясняется, как включить пакетную запись (оптимизация # 8) с использованием EclipseLink JPA 2.3 и базы данных Oracle. Посмотрите на аналогичные параметры конфигурации в вашей конкретной среды.

Ответ 2

В зависимости от того, заключает ли транзакция в цикле, пакетная операция обычно уже выполняется в вашем случае.

JPA будет собирать все ваши обновления в своем кеше L1 и, как правило, записывать все в БД в пакет, когда совершается транзакция. Это не так уж и отличается от пакетной обработки в JDBC, где каждый добавляемый пакетный элемент также временно находится в памяти, пока вы не вызовете метод обновления.

Потенциально проблематично то, что у вас нет твердых гарантий того, что JPA действительно делает эту доработку вообще, и если это происходит при транзакции или когда достигнут порог, но я обнаружил, что на практике почти во всех случаях и особенно в случаях включая такой простой цикл обновления, он действительно выполняет пакетную обработку.

Одна из проблем заключается в том, что даже если JPA действительно уже выполняет пакетную обработку, вы все же можете захотеть контролировать размер партии. Статьи, связанные с другими ответами, предоставляют для этого довольно полезную информацию.

Наконец, вы должны знать, что ваш кеш L1 продолжает расти в цикле, поэтому, если количество обновлений действительно велико, периодически его очищайте. В качестве альтернативы, если ваша бизнес-логика может ее поддерживать, выполните частичные обновления в нескольких транзакциях. Например. от 0 до 100 000 в транзакции 1, 100.001 до 200.000 в транзакции 2 и т.д.

Ответ 3

Я знаю, что это довольно старый вопрос с принятым ответом. Тем не менее, я бы хотел дать новый ответ на этот конкретный вопрос "JPA-пакетные вставки".

@PersistenceContext
private EntityManager entityManager;

@Value("${hibernate.jdbc.batch_size}")
private int batchSize;

public <T extends MyClass> Collection<T> bulkSave(Collection<T> entities) {
  final List<T> savedEntities = new ArrayList<T>(entities.size());
  int i = 0;
  for (T t : entities) {
    savedEntities.add(persistOrMerge(t));
    i++;
    if (i % batchSize == 0) {
      // Flush a batch of inserts and release memory.
      entityManager.flush();
      entityManager.clear();
    }
  }
  return savedEntities;
}

private <T extends MyClass> T persistOrMerge(T t) {
  if (t.getId() == null) {
    entityManager.persist(t);
    return t;
  } else {
    return entityManager.merge(t);
  }
}

Источник: http://frightanic.com/software-development/jpa-batch-inserts/

Ответ 4

JPA сам по себе не имеет настроек для пакетной обработки. Однако существуют некоторые зависящие от реализации настройки. Вот пример для спящего режима.