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

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

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

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

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

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

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

4 ответов


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


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

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

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

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

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


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

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


JPA сам по себе не имеет никаких настроек для дозирования. Однако существуют некоторые параметры, зависящие от реализации. вот пример для hibernate.