2013-08-28 12 views
8

Ho visto molti commenti in articoli dello stack-overflow ho trovato alcune cose su entrambi i @Transactional uso con @Service o con @ControllerPerché utilizzare @Transactional con @Service invece che con @Controller

"Di solito, uno dovrebbe mettere una transazione al livello di servizio."

"Il caso normale sarebbe quella di annotare su un livello di livello di servizio"

"operazioni marchio Think appartengono al livello di servizio. E 'quello che sa di unità di lavoro e casi d'uso. E' la risposta giusta se si avere diversi DAO immessi in un servizio che devono collaborare in un'unica transazione. " [Source]

svantaggio di utilizzare @Transactional con lo strato @service

Se ho avuto 2 metodi per esempio saveUser() e saveEmail() (perché devo conservare le email in un database per inviargli il presente più tardi - come una coda) creerei nel mio servizio un metodo saveUserAndSendEmail (utente User) che sarebbe transazionale. [Source]

Significa creo molti metodi a livello di servizio al posto di uno Salva metodo generico come segue

public <T> long save(T entity) throws DataAccessException { 
    Session session = sessionFactory.getCurrentSession(); 
    long getGenVal=(Long) session.save(entity); 
    return getGenVal; 
} 

Secondo la soluzione di cui sopra, significa che abbiamo molti metodi come segue LOL. .

public <T> long saveAccount(T entity)....

public <T> long saveWithAuditLog(T entity, K entity1)....

public <T> long saveWithAuditLogAndEntries(T entity, K entity, M entity)....

superare questa situazione

UTILIZZO DEL @Transactional in @Controller e solo fare un generico metodo di salvataggio e salvare tutti i soggetti/modello utilizzando questo semplice metodo save. e se qualche metodo non riesce a salvare tutte le transazioni nel rollback del controller con successo.

altra situazione che assicurare che @Transactional dovrebbe essere utilizzato con @Controller

In @Controller:

pt.save(entity1); 
pt.save(entity2); 
int a = 2/0; 
pt.save(entity3); 

Nel caso in cui, @Transactional il servizio, prima 2 entità con successo salvato ma terzo non è un rollback di tutte le transazioni

Nel caso, @Transactional su @Controller tutte le tran il rollback della sottrazione avviene come eccezione

perché il sovraccarico di stack ha chiesto "Non eseguire transazioni nel controller.Metteteli nelle classi di livello di servizio. "? [source]

+0

Si prega di non utilizzare il codice markup per il testo. È possibile utilizzare le virgolette di blocco per le citazioni, se lo si desidera. – Flexo

+3

Penso che la soluzione migliore nel caso sia creare un altro livello di livello tra 'controller' e' service'. Come vedo io, il 'controller' gestisce solo le chiamate e prepara i vars per gestire e fare la logica su di essi. Il 'servizio' gestisce tutte le cose del DB. e il modello che dovrebbe trovarsi tra 'controller' e' service' può fare qualche logica. Nel tuo esempio fare poche azioni di salvataggio è un'azione logica sui dati. che significa metterli in 'model' e warp' model' con 'transactional' se necessario – oak

+0

I metodi' saveUser() 'e' saveEmail() 'dovrebbero essere nel livello DAO. Quindi fai il metodo 'saveUserAndSendEmail (utente utente)' nel livello di servizio Transazionale. – xli

risposta

15

Stai chiedendo circa le migliori pratiche e delle migliori pratiche è quello di segnare @Transactional nel livello di servizio perché un @Controller non dovrebbe essere a conoscenza di persistenza dei dati in una logica MVC.
@Service è costruito sul caso d'uso generato dall'analisi e conosce l'unità di lavoro e viene anche realizzato pensando in termini di riutilizzo: se si passa da un contesto Web a uno desktop (ad esempio, o qualche altro frontend visivo) dove @Controller il livello non esiste non hai problemi perché tutto è incapsulato nel livello di servizio.
A @Service A è un contratto e una modifica in presentatio n layer non dovrebbe richiedere la riscrittura del codice @Service.
Ma a Spring non importa dove si mettono i confini della transazione, è possibile utilizzare @Controller ma la propria applicazione potrebbe essere più difficile da gestire.

Spero che questo sia abbastanza chiaro. Scusate se non; L'inglese non è la mia lingua madre.

0

Il controller è saldamente nel livello di visualizzazione, che può essere modificato in qualsiasi momento. Il servizio possiede ancora unità di lavoro e dovrebbe funzionare correttamente indipendentemente dalla vista che sta accedendo. La mia risposta here è ancora valida.

+0

Significa che devo creare molti metodi per salvare come 'saveAccount'' saveAccountAudit' 'saveAccountAuditEntries'? –

1

Ho creato un servizio di livello superiore che utilizza altri servizi (non transazionali). E il servizio di livello superiore è transazionale.

@Service 
public class Service1Impl implements Servcie1 { 
    public Object method11(){...} 
    public Object method12(){...} 
} 

@Service 
public class Service2Impl implements Service2 { 
    public method21(){...} 
} 

public interface Service1 { 
    public Object method11(); 
    public Object method12(); 
} 

public interface Service2 { 
    public Object method21(); 
} 

@Transactional 
public interface UpperLayerService {} 

@Service 
public class UpperLayerServiceImpl implements UpperLayerService { 
    @Autowired 
    private Service2 service2; 
    @Autowired 
    private Service3 service3; 

    public Object doWork() { 
     Object o1 = service1.method11(); 
     Object o2 = service1.method12(); 
     Object o3 = service2.method21(); 
     .... 
     Object res = null;//...Any code 
     return res; 
    } 
} 
2

solo così altre conoscenze, le annotazioni di interfaccia sono scoraggiati

Primavera consiglia di annotare solo classi concrete (e metodi di classi concrete) con l'annotazione @Transactional, al contrario di annotare le interfacce. È certamente possibile posizionare l'annotazione @Transactional su un'interfaccia (o un metodo di interfaccia), ma funziona solo come ci si aspetterebbe se si utilizzano proxy basati su interfaccia. Il fatto che le annotazioni Java non siano ereditate dalle interfacce significa che se si utilizzano i proxy basati sulla classe (proxy-target-class = "true") o l'aspetto basato sulla tessitura (mode = "aspectj"), allora le impostazioni della transazione sono non riconosciuto dall'infrastruttura di proxy e tessitura, e l'oggetto non verrà incapsulato in un proxy transazionale, il che sarebbe decisamente negativo.

Problemi correlati