Domanda

Ho appena saltato su una caratteristica scritto da qualcun altro che sembra un po 'inefficiente, ma la mia conoscenza di APP non è buona per trovare una soluzione portatile che non è Hibernate specifico.

In sintesi il metodo Tao chiamata all'interno di un ciclo per inserire ciascuna delle nuove entità fa un "entityManager.merge (oggetto);".

Isnt' c'è un modo definito nelle specifiche JPA per passare un elenco degli enti al metodo Dao e fare un inserimento di massa / lotto invece di chiamare unione per ogni singolo oggetto?

Inoltre poiché il metodo Dao è annotato w / "@Transactional" Mi chiedo se ogni singola chiamata merge sta accadendo all'interno della propria transazione ... che non aiuterebbe le prestazioni.

Qualche idea?

È stato utile?

Soluzione

Non v'è alcuna operazione di inserimento dei lotti in JPA vaniglia.

Si, ogni inserto sarà fatto all'interno della propria transazione. L'attributo @Transactional (senza qualificatori), un livello di propagazione di REQUIRED (creare una transazione se non esiste già). Supponendo di avere:

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

si esegue questa operazione:

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;
  }
}

In questo modo l'intero gruppo di inserti viene avvolto in una singola transazione. Se si sta parlando di un numero molto elevato di inserti si consiglia di dividerlo in gruppi di 1000, 10000 o quello che funziona come un numero sufficientemente ampio transazione senza commit può morire di fame il database delle risorse ed eventualmente fallire a causa di sola dimensione.

Nota: @Transactional è un'annotazione di primavera. Vedere transazionale Gestione dalla Primavera di riferimento.

Altri suggerimenti

Che cosa si potrebbe fare, se si fosse in uno stato d'animo furbo, è:

@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

A causa della cascata, che farà sì che i soggetti da inserire in una sola operazione.

Dubito che ci sia alcun vantaggio pratico per fare questo oltre semplicemente persistente singoli oggetti in un ciclo. Sarebbe un interessante esaminare il codice SQL che l'implementazione JPA emessa, e punto di riferimento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top