Pregunta

Me salté en una función escrita por otra persona que parece un poco ineficiente, pero mi conocimiento de la APP no es tan bueno para encontrar una solución portátil que no está Hibernate específica.

En pocas palabras el método Dao llamada dentro de un bucle para insertar cada una de las nuevas entidades realiza una "EntityManager.merge (objeto);".

No queremos que existe una forma definida en las especificaciones de la APP para pasar una lista de entidades en el método Dao y hacer una inserción masiva / lote en lugar de llamar de mezcla para cada objeto?

Además, puesto que el método Dao se anota w / "@Transactional" Me pregunto si cada llamada de combinación única está sucediendo dentro de su propia transacción ... lo que no ayudaría rendimiento.

¿Alguna idea?

¿Fue útil?

Solución

No hay ninguna operación de lote en JPA vainilla.

Sí, cada inserto se llevará a cabo dentro de su propia transacción. El atributo @Transactional (sin calificadores) significa un nivel de propagación de REQUIRED (crear una transacción si no existe ya). Asumiendo que tiene:

public class Dao {
  @Transactional
  public void insert(SomeEntity entity) {
    ...
  }
}

hacer esto:

public class Batch {
  private Dao dao;

  @Transactional
  public void insert(List<SomeEntity> entities) {
    for (SomeEntity entity : entities) {
      dao.insert(entity);
    }
  }

  public void setDao(Dao dao) {
    this.dao = dao;
  }
}

De esta manera todo el grupo de insertos se envuelve en una sola transacción. Si estamos hablando de un gran número de inserciones es posible que desee dividirlo en grupos de 1.000, 10.000 o lo que funcione como una transacción no confirmada suficientemente grande puede morir de hambre la base de datos de los recursos y, posiblemente, fallar debido al tamaño solo.

Nota: @Transactional es una anotación de primavera. Ver Gestión transaccional desde la primavera de referencia.

Otros consejos

Lo que podría hacer, si estuviera en un estado de ánimo astuto, es la siguiente:

@Entity
public class SomeEntityBatch {

    @Id
    @GeneratedValue
    private int batchID;
    @OneToMany(cascade = {PERSIST, MERGE})
    private List<SomeEntity> entities;

    public SomeEntityBatch(List<SomeEntity> entities) {
        this.entities = entities;
    }

}

List<SomeEntity> entitiesToPersist;
em.persist(new SomeEntityBatch(entitiesToPersist));
// remove the SomeEntityBatch object later

Debido a la cascada, que hará que las entidades a ser insertados en una sola operación.

Dudo que haya ninguna ventaja práctica para hacer esto una simple persistencia de objetos individuales en un bucle. Sería interesante analizar el SQL que la aplicación APP emitido, y para referencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top