2011-11-09 13 views
7

Tengo una clase @Service que tiene un método @Transactional que llama a otro método @Transactional en la misma clase. Estaba probando el comportamiento de reversión para esto y descubrí que no funcionaba correctamente. El código es como la siguiente:Spring anidado @Método transaccional y retrotracción

@Service 
public class DefaulService implements ervice 
{ 
    @Transactional 
    public void methodOne() 
    { 
     methodTwo(); 

      //question edited 
      //this seems to be the problem 
      this.serviceDAO.executeUpdateOperation(); 

     //test rollback 
     throw new RuntimeException(); 
    } 

    @Transactional 
    public void methodTwo() 
    { 
     //DAO stuff 
    } 
} 

Después de ejecutar metadona puedo comprobar la base de datos y los cambios están ahí, a pesar de que el registro muestra "JDBCTransaction - rollback".

Si invoco methodTwo de forma individual y agrego una excepción al final, los cambios se retrotraen correctamente.

¿Hay alguna manera de realizar los cambios de methodOne rollback correctamente que se produjeron durante la llamada @Transactional anidada? Tenía la impresión de que la propagación predeterminada de REQUIRED lo lograría, pero parece que no funciona. Gracias

ACTUALIZACIÓN

Ok, acabo notó algo más. Justo antes del lanzamiento de la excepción, llamo al dao del servicio y realizo una actualización manual a través de 'executeUpdate'. Si comento esta línea, la reversión anidada funciona. Parece que el problema es llamar al DAO y ejecutar la consulta executeUpdate. Pero, ¿no debería funcionar también dentro de la transacción actual?

+0

¿Sabía que cuando se invoca 'methodTwo()' de la anotación 'methodOne()' '@ Transactional' sobre la anterior se ignora? Ver mi [artículo] (http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html) para más detalles. Sin embargo, esto no está causando sus problemas, pero vale la pena saberlo. –

+0

Sí, pero dado que MethodTwo se puede llamar de forma independiente, entonces necesita su propia anotación para tales casos. En este momento estoy perplejo sobre por qué executeUpdate hace que la transacción se comprometa, aunque tal vez ese sea el comportamiento predeterminado. – JayPea

+1

¿cuál es la propagación de la transacción de serviceDao? ¿Es por casualidad REQUERES_NEW? – Hendrik

Respuesta

1

Usted está definitivamente obteniendo la instancia del "servicio" de la fábrica de frijoles cuando llama a los métodos, ¿verdad? La fábrica de beans necesita configurar un proxy que implemente la lógica transaccional alrededor de cada llamada de método. Tenía la impresión de que esto solo funcionaba cuando "externos" invocan métodos a través del proxy, y no necesariamente funciona cuando un método llama a otro, ya que ese método es una llamada directa dentro del objeto de implementación y no pasa por el proxy AOP.

+0

Esto depende del tipo de enfoque de AOP que esté utilizando. Compruebe el [enlace] (http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html) de Tomasz Nurkiewicz. Además, eso no puede explicar el comportamiento que JayPea está describiendo. –

Cuestiones relacionadas