2012-05-14 18 views
23

C'è un modo in cui è possibile utilizzare gli inserimenti batch utilizzando EntityManager JPA. So che non esiste un modo diretto per raggiungere questo obiettivo, ma ci deve essere un modo per ottenere questo meccanismo.Inserimenti batch utilizzando JPA EntityManager

In realtà, per ogni operazione di inserimento mi occorrono 300ms che voglio ridurre utilizzando inserti batch anziché singoli inserti.

Ecco codice che sto usando attualmente in esecuzione per inserti singoli

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

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

grazie in anticipo.

risposta

11

E è possibile eseguire in batch scrive utilizzando JPA, ma è fortemente dipendente dalla specifica implementazione del provider di persistenza, database e driver JDBC. Ad esempio, questo article spiega come abilitare la scrittura in batch (ottimizzazione n. 8) utilizzando EclipseLink JPA 2.3 e un database Oracle. Consulta i parametri di configurazione simili nel tuo ambiente particolare.

+0

Ciao, mi può fornire qualche frammento di codice come utilizzare lo stesso in codice di cui sopra previsto. – Ran

+0

@Rana come ho detto sopra: dipende da quale provider di persistenza stai usando - e non posso dirlo guardando il codice, devi dirmelo. –

+1

Ciao, sto usando org.eclipse.persistence.jpa.PersistenceProvider. Inoltre, per favore fatemi sapere se ci sono delle limitazioni utilizzando gli inserti batch. – Ran

21

A seconda che la transazione includa il ciclo, in genere il batching avviene nel tuo caso.

JPA raccoglierà tutti gli aggiornamenti nella sua cache L1 e in genere scriverà tutto sul DB in un batch quando la transazione viene eseguita. Questo non è poi così diverso con il batching in JDBC, in cui ogni elemento batch che aggiungi è temporaneamente in memoria fino a quando non chiami un metodo di aggiornamento.

potenzialmente problematico è che non si dispone di garanzie dure che APP effettivamente questo dosaggio a tutti e se lo fa a transazione commit o quando viene raggiunta una soglia, ma ho trovato che in pratica in quasi tutti i casi, e in particolare in casi che coinvolgono un ciclo di aggiornamento così semplice, in effetti fa il batching.

Un problema è che anche se JPA esegue effettivamente il batch, è comunque possibile che si desideri controllare le dimensioni del batch. Gli articoli collegati dalle altre risposte forniscono informazioni piuttosto utili per questo.

Infine, si dovrebbe essere consapevoli che la cache L1 continua a crescere in un ciclo, quindi se il numero di aggiornamenti è veramente grande, periodicamente cancellarlo. In alternativa, se la logica aziendale può sostenerlo, eseguire aggiornamenti parziali in più transazioni. Per esempio. da 0 a 100.000 nella transazione 1, da 100.001 a 200.000 nella transazione 2, ecc.

+0

Ehi, ho usato spring data jpa ora, quindi intendi se aggiorno l'oggetto in un ciclo all'interno di un metodo e questo metodo è contrassegnato da @Transactional, verrà automaticamente aggiornato come l'aggiornamento batch jdbc. – zhuguowei

12

So che questa è una domanda abbastanza vecchia con una risposta accettata. Tuttavia, mi piacerebbe dare una nuova risposta a questo argomento molto specifico "inserti batch 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); 
    } 
} 

Fonte: http://frightanic.com/software-development/jpa-batch-inserts/

+2

Suppongo che dobbiamo nuovamente "flush()" e "clear()" alla fine per salvare gli oggetti rimanenti che non hanno completato la dimensione del batch? –

+0

Suoni giusti, grazie a @RamPatra. –

Problemi correlati