Пакетные вставки с помощью 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.