2009-06-21 14 views
9

Sto lavorando a un'app Java che utilizza le classi Spring IoC e JDBC Template. Ho una classe DAO che ha 4 metodi: m1() a m4(). m1 esegue più inserti e gli aggiornamenti sulla tabella t1, t2 m2 sul tavolo, m3 in t3, eccTransazioni facili con Spring JDBC?

I metodi DAO vengono utilizzati come segue:

while(true) 
{ 
    //process & generate data 

    dao.m1(data1); 
    dao.m2(data2); 
    dao.m3(data3); 
    dao.m4(data4); 

    //sleep 
} 

voglio le operazioni db sotto il 4 metodo consecutivo chiama per essere atomico, o tutte e 4 le tabelle sono state aggiornate con successo o nessuna lo sono. Pertanto, se si verifica un errore durante l'esecuzione delle operazioni in m3(), si desidera ripristinare tutte le modifiche (aggiornamenti & inserti) eseguite in m2 & m1.

Così molla ti consente di farlo nel modo seguente?

while (true) 
{ 
    //process & generate data 

    transaction = TransactionManager.createNewTransaction(); 

    transaction.start() 

    try 
    { 
    dao.m1(data1); 
    dao.m2(data2); 
    dao.m3(data3); 
    dao.m4(data4); 
    } 
    catch(DbUpdateException e) 
    { 
    transaction.rollBack(); 
    } 

    transaction.end(); 

    // sleep 

}

o ci sono modi migliori per farlo?

risposta

8

Per completezza, la soluzione programmatica sarebbe:

private TransactionTemplate transactionTemplate; 

public setTransactionManager(PlatformTransactionManager transactionManager) { 
    this.transactionTemplate = new TransactionTemplate(transactionManager); 
} 

... 

while (true) { 

    transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
    protected void doInTransactionWithoutResult(TransactionStatus status) { 
     try { 
     dao.m1(data1); 
     dao.m2(data2); 
     dao.m3(data3); 
     dao.m4(data4); 
     } catch(DbUpdateException e) { 
     status.setRollbackOnly(); 
     } 
    } 
    }); 
} 
1

Sì, è possibile inserire tali chiamate in un metodo e specificare le transazioni declaratively.

Non è necessario aggiungere questo codice: Spring lo può fare per te.

15

Sì Spring consente di programmatically control transactions.

Personalmente preferisco declarative transactions utilizzando annotazioni, che va in questo modo:

public void runBatchJob() { 
    while (true) { 
    // generate work 
    doWork(unitOfWork); 
    } 
} 

@Transactional 
private void doWork(UnitOfWork work) { 
    dao.m1(data1); 
    dao.m2(data2); 
    dao.m3(data3); 
    dao.m4(data4); 
} 

in cui vengono definite le funzioni DAO:

@Transactional 
public void m1(Data data) { 
    ... 
} 

Questo richiede nella vostra applicationContext.xml:

<tx:annotation-driven/> 

Declarat Le transazioni possono essere dichiarate per richiedere una transazione, richiedere una nuova transazione, supportare le transazioni, ecc. Il rollback avverrà quando un blocco annotato con @Transactional lancia un RuntimeException.

+0

Non credo è necessario annotare il m1, m2, ecc come @Transactional. Se qualcuno lancia un'eccezione, verrà eseguito il rollback di tutto ciò che è già stato completato da doWork. – Chadwick

+0

Non è necessario in questo contesto, no. Ma se stanno facendo degli aggiornamenti, dovresti annotarli come richiedono le transazioni, altrimenti potresti trovarti ad eseguire aggiornamenti non transazionali se li chiami al di fuori del contesto doWork(). – cletus

+0

L'annotazione @Transactional fa qualcosa quando viene applicata a un metodo privato? –

1

Primavera in grado di gestire tutto questo per voi utilizzando @Transactional come spiegato o in XML, se si preferisce.

La cosa importante da ottenere è il tipo di Propagazione della transazione che si desidera e tutto dipende dall'applicazione.

Per impostazione predefinita verrà avviata una transazione se non esiste, e verrà riutilizzata una transazione esistente se ne è già stata avviata. Questo è il comportamento che si desidera se si desidera che tutti e 4 i DAO siano atomici.

Metti @Transactional su una classe che gestirà i metodi DAO chiamati (MyService) - qualsiasi cosa al di sotto di questo livello ora prenderà parte a quel limite di transazione.

i.e:

@Transactional 
public void m1(Data data) { 
... 
} 

@Transactional 
public void m2(Data data) { 
... 
} 

Fare questo codice non è necessario.

Vedi here for more info

Problemi correlati