Inserciones por lotes utilizando JPA EntityManager


Hay una manera en la que podemos usar inserciones por lotes usando EntityManager de JPA. Sé que no hay una manera directa de lograr esto, pero debe haber alguna manera de lograr este mecanismo.

En realidad, para cada operación de inserción me está tomando 300ms que quiero reducir usando insertos por lotes en lugar de insertos individuales.

Aquí está el código que estoy usando actualmente ejecutando para inserciones individuales

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

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

Gracias de antemano.

Author: DataNucleus, 2012-05-14

4 answers

es posible realizar escrituras por lotes usando JPA, pero depende en gran medida de la implementación específica de su proveedor de persistencia, base de datos y controlador JDBC. Por ejemplo, este artículo explica cómo habilitar la escritura por lotes (optimización #8) usando EclipseLink JPA 2.3 y una base de datos Oracle.Busque parámetros de configuración similares en su entorno particular.

 12
Author: Óscar López,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-14 13:53:48

Dependiendo de si la transacción encierra el bucle, el procesamiento por lotes normalmente ya ocurre en su caso.

JPA recopilará todas sus actualizaciones en su caché L1, y normalmente escribirá todas en la base de datos en un lote cuando se confirme la transacción. Esto no es realmente tan diferente con el procesamiento por lotes en JDBC, donde cada elemento por lotes que agregue también está temporalmente en memoria hasta que llame a un método de actualización.

Potencialmente problemático es que no tiene garantías duras de que JPA de hecho hace este procesamiento por lotes en absoluto y si hace esto en commit transacción o cuando se alcanza un umbral, pero he encontrado que en la práctica en casi todos los casos y especialmente en los casos que implican un bucle de actualización tan simple, de hecho hace el procesamiento por lotes.

Un problema es que incluso si JPA ya hace el procesamiento por lotes, es posible que desee controlar los tamaños de los lotes. Los artículos vinculados por las otras respuestas proporcionan información bastante útil para eso.

Finalmente, debe tener en cuenta que su caché L1 mantiene creciendo en un bucle, por lo que si el número de actualizaciones es realmente grande, límpielo periódicamente. Alternativamente, si su lógica de negocio puede sostenerlo, haga actualizaciones parciales en varias transacciones. Por ejemplo, elemento 0 a 100.000 en la transacción 1, 100.001 a 200.000 en la transacción 2, etc.

 21
Author: Arjan Tijms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-15 09:06:33

Sé que esta es una pregunta bastante antigua con una respuesta aceptada. Sin embargo, me gustaría dar una nueva respuesta a este tema muy específico "inserciones por lotes 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/

 13
Author: Marcel Stör,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-24 07:59:22

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.

 3
Author: Sebastian Łaskawiec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-14 13:55:03