java - tutorial - Inserciones de lotes usando JPA EntityManager
jpa java se (4)
¿Hay alguna manera de utilizar inserciones por lotes utilizando JPA EntityManager? Sé que no hay una forma directa de lograr esto, pero debe haber alguna manera de lograr este mecanismo.
En realidad, para cada operación de inserción me está llevando 300ms, que quiero reducir usando inserciones de lotes en lugar de inserciones simples.
Aquí está el código que estoy usando actualmente para inserciones individuales
@PersistenceContext(unitName = "testing")
EntityManager eM;
Query querys = this.eM.createNativeQuery(insertQuery);
for (String s : someList) {
//setting parameters
querys.executeUpdate();
}
Gracias por adelantado.
Dependiendo de si la transacción incluye el bucle, el procesamiento por lotes generalmente ya ocurre en su caso.
JPA recopilará todas sus actualizaciones en su caché L1, y normalmente escribirá todo eso en la base de datos en un lote cuando la transacción se comprometa. En realidad, esto no es tan diferente con el procesamiento por lotes en JDBC, donde cada elemento del lote que agrega también está temporalmente en la memoria hasta que llame a un método de actualización.
Potencialmente problemático es que no tienes garantías duras de que JPA realmente haga este lote y si esto se realiza al momento de la transacción o cuando se alcanza un umbral, pero encontré eso en la práctica en casi todos los casos y especialmente en casos que involucran tal simple actualización de bucle, de hecho hace lotes.
Un problema es que incluso si JPA ya hace lotes, es posible que desee controlar los tamaños de lote. Los artículos vinculados por las otras respuestas proporcionan información bastante útil para eso.
Finalmente, debe tener en cuenta que su caché L1 sigue creciendo en un bucle, por lo que si el número de actualizaciones es realmente grande, límpielo periódicamente. Alternativamente, si la lógica de su negocio puede sustentarlo, realice actualizaciones parciales en varias transacciones. Por ejemplo, artículo 0 a 100.000 en la transacción 1, 100.001 a 200.000 en la transacción 2, etc.
Es posible realizar escrituras por lotes utilizando JPA, pero depende en gran medida de la implementación específica de su proveedor de persistencia, base de datos y el controlador JDBC. Por ejemplo, este article explica cómo habilitar la escritura por lotes (optimización n.º 8) utilizando EclipseLink JPA 2.3 y una base de datos Oracle. Busque parámetros de configuración similares en su entorno particular.
JPA por sí mismo no tiene ninguna configuración para el procesamiento por lotes. Sin embargo, hay algunas configuraciones dependientes de la implementación. Aquí hay un ejemplo para hibernar .
Sé que esta es una pregunta bastante antigua con una respuesta aceptada. No obstante, me gustaría dar una nueva respuesta a este tema tan específico "Inserciones de lote 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);
}
}
Fuente: http://frightanic.com/software-development/jpa-batch-inserts/