2014-04-17 14 views
27

Case1

@Transactional 
public class UserServiceImpl implements UserService { 

    ................... 
    public void method1(){ 
     try{ 
      method2(); 
     }catch(Exception e){ 

     } 
    } 
    public void method2(){ 

    } 
} 

Case2

public class UserServiceImpl implements UserService { 

    ................... 
    public void method1(){ 
     try{ 
      method2(); 
     }catch(Exception e){ 

     } 
    } 
    @Transactional 
    public void method2(){ 

    } 
} 

In case1 eventuale eccezione si verifica che rollback sta funzionando, ma nel caso in cui 2 non funziona. Ci sono problemi di prestazioni se seguo il caso1?Qual è la differenza tra la definizione @Transactional sulla classe vs metodo

risposta

10

Citando here

La raccomandazione del team di Primavera è che si annotare solo classi concrete con l'annotazione @Transactional, al contrario di annotare le interfacce.

Poiché questo meccanismo si basa sui proxy, unico metodo 'esterno' chiamate in ingresso tramite il proxy sarà intercettato. Ciò significa che l '"autoinvocazione", ovvero un metodo all'interno dell'oggetto target che chiama un altro metodo dell'oggetto target, non porterà a una transazione effettiva in fase di esecuzione anche se il metodo richiamato è contrassegnato con @Transactional!

+5

Questo non indica la differenza tra il metodo annotato '@ Transactional' e la classe annotata' @ Transactional'. –

+1

@kocko> Ho pensato che l'OP seguirà il collegamento, tuttavia ho appena aggiornato la mia risposta, per favore date un'occhiata. – mok

24

@Transactional in una classe si applica a ciascun metodo sul servizio. È una scorciatoia. In genere, è possibile impostare @Transactional(readonly = true) su una classe di servizio, se si sa che tutti i metodi accederanno al livello del repository. È quindi possibile sovrascrivere il comportamento con @Transactional sui metodi che eseguono modifiche nel modello. Problemi di prestazioni tra 1) e 2) non noti.

5

Supponiamo di avere la seguente classe:

@Transactional(readOnly = true) 
public class DefaultFooService implements FooService { 

    public Foo getFoo(String fooName) { 
    // do something 
    } 

    // these settings have precedence for this method 
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 
    public void updateFoo(Foo foo) { 
    // do something 
    } 
} 

La @Transactional annotazione sul livello di classe sarà applicato ad ogni metodo nella classe.

Tuttavia, quando un metodo viene annotato con @Transactional (come, updateFoo(Foo foo)) questo richiederà precedenza sulle impostazioni transazionale definite a livello di classe.

Maggiori informazioni:

11

Nel caso 1 @Transactional viene applicato ad ogni singolo metodo. Nel caso 2 @Transactional viene applicato solo a method2(), non a method1()

Caso 1: - Metodo di richiamo1() -> viene avviata una transazione. Quando method1() chiama method2() non viene avviata nessuna nuova transazione, poiché ne esiste già una

Caso 2: - Metodo di richiamo1() -> non viene avviata alcuna transazione. Quando method1() chiama method2() NO viene avviata una nuova transazione. Questo perché @Transactional non funziona quando si chiama un metodo all'interno della stessa classe. Funzionerebbe se chiamassi method2() da un'altra classe.

Dal spring reference manual:

In modalità proxy (che è il default), solo metodo esterno chiamate in ingresso tramite il proxy sono intercettati. Ciò significa che l'auto-invocazione, in effetti, un metodo all'interno dell'oggetto target che chiama un altro metodo dell'oggetto target, non porterà a una transazione effettiva in fase di esecuzione anche se il metodo richiamato è contrassegnato con @Transactional. Inoltre, il proxy deve essere completamente inizializzato per fornire il comportamento previsto, pertanto non si deve fare affidamento su questa funzione nel codice di inizializzazione, ad esempio @PostConstruct.

Problemi correlati