2010-06-25 16 views

Respuesta

83

De http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

La recomendación del equipo de la primavera es que sólo anotar clases concretas con el @Transactional anotación, en contraposición a la anotación de las interfaces. Sin duda puede colocar la anotación @Transactional en una interfaz (o en un método de interfaz), pero esto solo funcionará como lo esperaría si está utilizando proxys basados ​​en interfaz. El hecho de que las anotaciones sean no heredadas significa que si está utilizando proxies basados ​​en clases, la infraestructura de proxys basada en clases no reconocerá la configuración de la transacción y el objeto no estará envuelto en un proxy transaccional (que sería decididamente malo). Así que, por favor, tome el consejo del equipo Spring y solo anote las clases concretas (y los métodos de las clases concretas) con la anotación @Transactional.

Nota: Dado que este mecanismo se basa en proxies, solo las llamadas a métodos 'externos' que entren a través del proxy serán interceptadas. Esto significa que la "auto invocación", es decir, un método dentro del objeto objetivo llamando a algún otro método del objeto objetivo, no dará lugar a una transacción real en tiempo de ejecución, incluso si el método invocado está marcado con @Transactional!

(Énfasis añadido a la primera frase, otra énfasis del original.)

+0

Big +1 Por cierto, me tomé la libertad de hacer una cita para que la gente no se confundiera, y agregó las letras itálicas y demás del original. –

+0

@ T.J. Crowder: increíble cómo cambian otras respuestas. thx, NP –

+0

He leído esta declaración antes en Spring docu, pero todavía no puedo entender por qué _transformación de transacción no será reconocida por la infraestructura de proxy basada en clase_? Personalmente creo que esto es solo una limitación de implementación de Spring, no el problema de la infraestructura proxy subyacente. –

0

Ponerlo en la interfaz está bien siempre y todos los implementadores previsibles de su cuidado de la CFI sobre los datos de TX (transacciones no son problemas que solo tratan las bases de datos). Si el método no se preocupa por TX (pero debe colocarlo allí para Hibernate o lo que sea), colóquelo en la impl.

También, podría ser un poco mejor colocar @Transactional en los métodos de la interfaz:

public interface FooService { 
    @Transactional(readOnly = true) 
    void doSmth(); 
} 
7

Usted puede poner en la interfaz, pero se advertirá que las transacciones pueden no terminar pasando en algunos casos. Vea el segundo consejo en Secion 10.5.6 de los documentos de la primavera:

primavera recomienda que sólo anotar clases concretas (y métodos de clases concretas) con la anotación @Transactional, en contraposición a la anotación de las interfaces. Ciertamente puede colocar la anotación @Transactional en una interfaz (o un método de interfaz), pero esto funciona solo como lo esperaría si está utilizando proxys basados ​​en interfaz. El hecho de que las anotaciones de Java no se hereden de las interfaces significa que si está utilizando proxies basados ​​en clases (proxy-target-class = "true") o el aspecto basado en weaving (mode = "aspectj"), entonces la configuración de la transacción es no reconocido por la infraestructura de proxying y weaving, y el objeto no estará envuelto en un proxy transaccional, lo cual sería decididamente malo.

Recomendaría ponerlos en la implementación por este motivo.

Además, para mí, las transacciones parecen un detalle de implementación, por lo que deberían estar en la clase de implementación. Imagine tener implementaciones de envoltura para el registro o implementaciones de prueba (simulaciones) que no necesitan ser transaccionales.

6

de primavera recommendation es que permite anotar las implementaciones concretas en lugar de una interfaz. No es incorrecto usar la anotación en una interfaz, solo es posible hacer un mal uso de esa función e ignorar inadvertidamente su declaración @Transaction.

Si marcó algo transaccional en una interfaz y luego se refiere a una de sus clases de implementación en otro lugar en primavera, no es del todo obvio que el objeto que crea la primavera no respetará la anotación @Transactional.

En la práctica se ve algo como esto:

public class MyClass implements MyInterface { 

    private int x; 

    public void doSomethingNonTx() {} 

    @Transactional 
    public void toSomethingTx() {} 

} 
2

Apoyo @Transactional en las clases concretas:

Prefiero diseñar una solución en 3 secciones en general: una API, un Im plementación y una red (si es necesario). Hago todo lo posible para mantener la API lo más ligera/simple/POJO posible minimizando las dependencias. Es especialmente importante si juegas en un entorno distribuido/integrado donde tienes que compartir mucho las API.

Poner @Transactional requiere bibliotecas Spring en la sección API, que en mi humilde opinión no es efectiva. Por lo tanto, prefiero agregarlo a la Implementación donde se ejecuta la transacción.

Cuestiones relacionadas