2010-10-07 10 views
5

Ho un'applicazione che utilizza Primavera 2,5 e Hibernate 3.Come set-up transazioni sia per applicazioni web e processi batch utilizzando primavera e Hibernate

C'è un'applicazione web con un livello di presentazione, uno strato servive e Livello DAO e alcuni lavori Quartz che condividono lo stesso servizio e i livelli DAO.

Le transazioni vengono inizializzati in diversi strati con annotazioni @Transactional, in questo modo:

alt text

E mi ha portato a un problema che ho descritto qui: Controlling inner transaction settings from outer transaction with Spring 2.5

ho letto un po 'su come impostare -up le transazioni per collegare Spring e Hibernate insieme. Sembra che l'approccio raccomandato sia quello di inizializzare le transazioni nel livello di servizio.

Quello che non mi piace è che la maggior parte delle transazioni esiste solo perché sono necessarie per il corretto funzionamento della sospensione.

E quando ho davvero bisogno di una transazione per un lavoro che chiama più metodi di servizio, sembra che non abbia una scelta per mantenere l'inizializzazione delle transazioni dai lavori. Quindi spostare le annotazioni @Transactional da DAO al servizio non sembra fare alcuna differenza.

Come suggeriresti di impostare le transazioni per questo tipo di applicazione?

+0

Ottima domanda e stavo per chiedere io stesso :) – willcodejavaforfood

+0

Aiutare con una domanda non è così gratificante come aiuto con una risposta, ma è ancora buono da ascoltare; o) – Damien

risposta

5

Ho letto un po 'su come impostare le transazioni per collegare Spring e Hibernate insieme. Sembra che l'approccio raccomandato sia quello di inizializzare le transazioni nel livello di servizio.

Definitivamente. demarcazione transazione dovrebbe essere fatto a livello livello di servizio, non a livello dello strato DAO:

  • l'unità di lavoro è il servizio, non il DAO
  • si desidera una transazione per abbracciano molteplici i DAO, se necessario.

Quello che non mi piace è che esistono maggior parte delle transazioni solo perché sono necessari per Hibernate per funzionare correttamente.

È consigliabile elaborare questa parte perché le transazioni non sono specifiche di Hibernate.

E quando ho davvero bisogno di una transazione per un lavoro che chiama più metodi di servizio, sembra che non abbia una scelta per mantenere l'inizializzazione delle transazioni dai lavori.

Se si desidera chiamare più servizi all'interno di una transazione avviata dallo strato di lavoro, dichiarare i propri servizi come transazionale con REQUIRED la semantica (il default) e si basano sulla propagazione delle transazioni primavera (questo vale a meno che non hai bisogno di una chiamata remota; in tal caso, utilizzare EJB).

Quindi spostare le annotazioni @Transactional da DAO al servizio non sembra fare alcuna differenza.

E fa fare la differenza e il fatto che è necessario per poter effettuare transazioni dallo strato di lavoro durante l'esecuzione batch non rende le cose diverse.

Consiglio vivamente di leggere lo Chapter 9. Transaction management.


(...) il mio problema principale deriva da Hibernate. Scusa se non ero chiaro.

Nessun problema. È solo che quando una domanda è vaga, si ottiene spesso una risposta vaga :)

Dalla documentazione di ibernazione: "Le transazioni di database non sono mai opzionali.Tutta la comunicazione con un database deve avvenire all'interno di una transazione.". Ecco perché gli sviluppatori mettono i metodi DAO transazionali sul mio progetto.

spiacenti ma la dichiarazione di cui sopra dice solo che il "comunicazione con un database deve avvenire all'interno di una transazione", niente di più, e decidere dove avviare la transazione è lasciato a vostra discrezione (in genere il servizio strato). Se lo fai a livello di DAO, cosa succede se chiama DaoFoo e e DaoBar non riesce? In questi casi, probabilmente vorrai eseguire il rollback di tutte le modifiche, non solo quelle eseguite in DaoBar. Da qui la necessità di controllare la transazione in cui inizia l'unità di lavoro.

IMHO, gli sviluppatori hanno bisogno di guida.

Ciò significa che tutti i miei servizi dovrebbero essere transazionali? Anche quando leggo i dati, ad esempio?

Prima di tutto, vi suggerisco di leggere Non-transactional data access and the auto-commit mode (il fratello minore del Sessions and transactions) per chiarire le cose circa "operazioni di sola lettura". Leggendo l'intera pagina è valsa la pena, ma lasciatemi citare questa parte specifica:

molti sviluppatori di applicazioni pensano di possono parlare con una banca dati al di fuori di una transazione . Questo ovviamente non è possibile ; Nessuna istruzione SQL può essere inviata a un database esterno a una transazione del database. Il termine accesso non transazionale significa che non ci sono limiti di transazione espliciti , nessuna transazione di sistema e che il comportamento di accesso ai dati è quello della modalità autocommit . Ciò non significa che nessuna transazione di database fisico sia implicata nello .

Una volta terminato il collegamento sopra, la prossima lettura suggerita sarà @Transactional read-only flag pitfalls. Ecco la parte rilevante:

(...) La linea di fondo è che quando si utilizza un framework basato su ORM , il flag di sola lettura è inutile e nella maggior parte dei casi viene ignorato in . Ma se si ancora insistono sull'uso di esso, impostare sempre la modalità di propagazione ai supporti, come mostrato nel Listato 9, in modo da nessuna transazione viene avviata:

Listing 9. Utilizzo di sola lettura e SUPPORTS modalità di propagazione per selezionare operazione

@Transactional(readOnly = true, propagation=Propagation.SUPPORTS) 
public TradeData getTrade(long tradeId) throws Exception { 
    return em.find(TradeData.class, tradeId); 
} 

Meglio ancora, basta evitare di utilizzare l'annotazione @Transactional tutto quando fa operazioni di lettura, come illustrato.210 in 10:

Listing 10. Rimozione del @Transactional annotazioni per selezionare operazioni

public TradeData getTrade(long tradeId) throws Exception { 
    return em.find(TradeData.class, tradeId); 
} 
+0

Grazie per le vostre spiegazioni Pascal. Ovviamente leggo il capitolo 9 ma il mio problema principale viene da Hibernate. Scusa se non ero chiaro. Dalla documentazione di ibernazione: "Le transazioni di database non sono mai opzionali.Tutta la comunicazione con un database deve avvenire all'interno di una transazione.". È per questo che gli sviluppatori mettono i metodi DAO transazionali sul mio progetto. Significa che tutti i miei servizi dovrebbero essere transazionali? Anche quando leggo i dati, ad esempio? – Damien

+0

@Pascal Grazie per il vostro tempo e chiarimenti. – Damien

+0

@Damien Prego, l'hai trovato utile –

Problemi correlati