2010-10-07 17 views
5

tengo una aplicación que utiliza Spring 2.5 y Hibernate 3.Cómo configuración transacciones tanto para aplicaciones web y trabajos por lotes utilizando Spring e Hibernate

Hay una aplicación web con una capa de presentación, una capa mas el servicio y una Capa DAO, así como algunos trabajos de Quartz que comparten el mismo servicio y las capas DAO.

Las transacciones se inicializan en diferentes capas con anotaciones @Transactional, así:

alt text

Me llevó a un problema que he descrito aquí: Controlling inner transaction settings from outer transaction with Spring 2.5

He leído un poco sobre cómo configurar transacciones para conectar Spring e Hibernate juntos. Parece que el enfoque recomendado es inicializar las transacciones en la capa de servicio.

Lo que no me gusta es que la mayoría de las transacciones existen solo porque son necesarias para que hibernate funcione correctamente.

Y cuando realmente necesito una transacción para un trabajo llamando a varios métodos de servicio, parece que no tengo otra opción para seguir inicializando las transacciones de los trabajos. Por lo tanto, mover las anotaciones @Transactional de DAO al servicio no parece hacer ninguna diferencia.

¿Cómo recomendaría establecer transacciones para este tipo de aplicación?

+0

Excelente pregunta y yo estaba a punto de preguntar por mí mismo :) – willcodejavaforfood

+0

ayudar con una pregunta no es tan gratificante como ayudar con una respuesta, pero aún así es bueno escuchar; o) – Damien

Respuesta

5

Leí un poco sobre cómo configurar las transacciones para conectar Spring e Hibernate juntas. Parece que el enfoque recomendado es inicializar las transacciones en la capa de servicio.

Definitivamente. demarcación de la transacción debe hacerse a nivel de capa de servicio, no al nivel de la capa DAO:

  • la unidad de trabajo es el servicio, no el DAO
  • desea una transacción para abarcar varios DAOs si es necesario.

Lo que no me gusta es que la mayoría de las transacciones sólo existen porque son necesarios para la hibernación para que funcione correctamente.

Quizás deba elaborar esta parte porque las transacciones no son específicas de Hibernate.

Y cuando realmente necesito una transacción para un trabajo llamando a varios métodos de servicio, parece que no tengo la opción de seguir inicializando las transacciones de los trabajos.

Si desea llamar a varios servicios dentro de una transacción iniciada a partir de la capa de empleo, declarar sus servicios como transaccional con REQUIRED semántica (por defecto) y se basan en la propagación de transacciones primavera (esto se aplica a menos que necesite una llamada remota; en ese caso, use EJB).

Por lo tanto, mover las anotaciones @Transactional de DAO al servicio no parece hacer ninguna diferencia.

Se hace hacer la diferencia y el hecho de que usted necesita para iniciar las transacciones de la capa de empleo cuando se ejecuta lotes no hace las cosas diferentes.

Recomiendo encarecidamente leer el Chapter 9. Transaction management.


(...) mi principal problema viene de hibernación. Lo siento si no estaba claro.

No hay problema. Es sólo que cuando una pregunta es vaga, muchas veces se recibe una respuesta vaga :)

De la documentación de hibernación: "transacciones de base de datos nunca son opcionales Toda la comunicación con una base de datos tiene que ocurrir dentro de una transacción..". Es por eso que los desarrolladores ponen métodos DAO transaccionales en mi proyecto.

Lo sentimos pero la declaración anterior sólo dice que el "comunicación con una base de datos tiene que ocurrir dentro una transacción", nada más, y decidir dónde iniciar la transacción se deja a su discreción (por lo general el servicio capa). Si lo hace en el nivel DAO, ¿qué ocurre si MySuperService llama al DaoFoo y DaoBar y DaoBar falla? En tales casos, es probable que desee deshacer todos los cambios, no solo los realizados en DaoBar. De ahí la necesidad de controlar la transacción donde comienza la unidad de trabajo.

En mi humilde opinión, los desarrolladores necesitan alguna orientación.

¿Eso significa que todos mis servicios deben ser transaccionales? Incluso cuando acabo de leer datos, por ejemplo?

En primer lugar, sugiero leer Non-transactional data access and the auto-commit mode (el hermano pequeño del Sessions and transactions) para aclarar las cosas sobre de "sólo lectura" transacciones. La lectura de toda la página es la pena, pero permítanme citar esta parte específica:

Muchos desarrolladores de aplicaciones creen que pueden hablar con una base de datos fuera de una transacción . Esto obviamente no es posible; no se puede enviar una declaración SQL a una base de datos fuera de una base de datos transacción. El término acceso a datos no transaccional significa que no hay límites de transacción explícitos , ninguna transacción del sistema , y que el comportamiento de acceso a datos es el del modo de confirmación automática . No significa que no las transacciones físicas de la base de datos son involucradas.

Una vez que haya terminado con el enlace de arriba, la próxima lectura sugerida será @Transactional read-only flag pitfalls. Aquí está la parte relevante:

(...) La conclusión es que cuando usa un marco basado en ORM, el indicador de solo lectura es bastante inútil y en se ignora la mayoría de los casos. Pero si todavía insisten en usarlo, ajuste siempre el modo de propagación a SOPORTES, como se muestra en el listado 9, por lo que no hay ninguna transacción se inicia:

Listado 9. El uso de sólo lectura y SUPPORTS modo de propagación de seleccione operación

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

Mejor aún, simplemente evitar el uso de la @Transactional anotación por completo al hacer las operaciones de lectura, como se muestra en el Listado 10:

Listado 10. Extracción de la anotación @Transactional para ciertas operaciones

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

Gracias por sus explicaciones Pascal. Obviamente leí el Capítulo 9, pero mi problema principal proviene de Hibernate. Lo siento si no estaba claro. De la documentación de hibernación: "Las transacciones de la base de datos nunca son opcionales. Toda comunicación con una base de datos tiene que ocurrir dentro de una transacción". Es por eso que los desarrolladores ponen métodos DAO transaccionales en mi proyecto. ¿Eso significa que todos mis servicios deberían ser transaccionales? Incluso cuando acabo de leer datos, por ejemplo? – Damien

+0

@Pascal Gracias por su tiempo y aclaraciones. – Damien

+0

@Damien De nada, me alegro de que lo haya encontrado útil –

Cuestiones relacionadas