Пакетные вставки с использованием JPA EntityManager
Можно ли использовать пакетные вставки с помощью JPA EntityManager. Я знаю, что нет прямого способа достичь этого, но должен быть какой-то способ достичь этого механизма.
Собственно, для каждой операции вставки он принимает 300 мс, которые я хочу уменьшить, используя пакетные вставки вместо одиночных вставок.
Здесь код, который я использую в настоящее время для одиночных вставок
@PersistenceContext(unitName = "testing")
EntityManager eM;
Query querys = this.eM.createNativeQuery(insertQuery);
for (String s : someList) {
//setting parameters
querys.executeUpdate();
}
Спасибо заранее.
Ответы
Ответ 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 сам по себе не имеет настроек для пакетной обработки. Однако существуют некоторые зависящие от реализации настройки. Вот пример для спящего режима.