Spring 1.2 manejo de transacciones declarativo

Uno de los avances más sonados de Spring es la posibilidad de manejar transacciones de manera declarativa, hasta ahora nunca se ha hablado de ello así que va siendo hora de que también tenga su huequecito en el blog. Los que os intereseís por este tema descubrireís que esto ha ido evolucionando y que la forma de hacerlo en Spring 1.2 difiere de cómo hacerlo en Spring 2.0 así que intentaré abarcar todas las posibilidades para que nada se quede fuera pero para no liar lo haré en varios post en este post me centraré en Spring 1.2.

Hay que declarar varios beans en el contexto de Spring para que se pueda realizar:

El manejador de Transacciones:

< bean id="transactionManager"

class=”org.springframework.jdbc.datasource.DataSourceTransactionManager”>

< property name="dataSource" ref="dataSource" />

< /bean >

El Data Source

< bean id="dataSource"

class=”org.apache.commons.dbcp.BasicDataSource”

destroy-method=”close”>

< property name="driverClassName"

value=”org.hsqldb.jdbcDriver”/>

< property name="url"

value=”jdbc:hsqldb:hsql://localhost:9001″/>

< property name="username" value="sa"/>

< property name="password" value=""/>

< / bean>

La plantilla del framework que utilicemos para persistencia en mi caso Ibatis

< bean id="sqlMapClient"

class=”org.springframework.orm.ibatis.SqlMapClientFactoryBean”>

value=”classpath:org/mipaquete/core/dao/ibatis/sql-map-config.xml”/>

< property name="dataSource" ref="dataSource" />

< /bean>

El aspecto transaccional que aplicaremos a la lógica de negocio

< bean id="baseTransactionProxy"

class=”org.springframework.transaction.interceptor.TransactionProxyFactoryBean”

abstract = “true”>

< property name="transactionManager" ref="transactionManager" />

< property name="transactionAttributes">

< props>

< prop key="get*">

PROPAGATION_REQUIRED,
readOnly,ISOLATION_DEFAULT
< /prop >
< prop key="*" >
PROPAGATION_REQUIRED,
ISOLATION_DEFAULT
< /prop >
< /props>

< / property>

< /bean>

Esta clase es la que tiene todo el meollo, como se puede observar Spring permite utilizar expresiones regulares a la hora de aplicar transacciones a nuestros métodos. Hay que explicar 2 cosas que significa PROPAGATION_REQUIRED y para que vale readOnly. La primera especifica que si existe una transacción en curso se añada el método a este contexto si se desea que se ejecute en una nueva transacción se puede utilizar PROPAGATION_REQUIRED_NEW, en cuanto a readOnly es una optimización para métodos transaccionales de lectura. Como mi proyecto era pequeño yo he utilizado el nivel de aislamiento por defecto.

A raíz del nivel de aislamiento en la web de IBM se ha publicado un artículo hablando de que la librería jta.jar (la que utiliza Spring) no soporta los niveles de aislamiento convencionales (Serializable,ReadCommited,RepeteableRead,ReadUncommited) y da una solución un tanto complicada en mi opinión al problema, yo no lo he probado, pero los que queraís aventuraros teneís la posibilidad en esta URL:

http://www-128.ibm.com/developerworks/java/library/j-isolation/

Ahora tan sólo restaría aplicar el aspecto a nuestras clases de la lógica de negocio:

< bean id="facade"
parent=”baseTransactionProxy” >
< property name="target" >
< bean class="org.mipaquete.core.domain.logic.FacadeImpl" >
< property name="aplicacionDao" ref="aplicacionDao"/ >
< /bean >
< /property >
< /bean>

< bean id="aplicacionDao"
class=”org.mipaquete.core.dao.ibatis.AplicacionDaoImpl” >
< property name="sqlMapClient" ref="sqlMapClient"/ >
< /bean>

Para los que esteís interesados podeís encontrar más información en la documentación de Spring en esta página:

http://www.springframework.org

10 Comentarios

  • 1. Spring 2.0 manejo declara&hellip  |  marzo 9th, 2007 at 7:22 pm

    [...] Continuando con en post sobre manejo declarativo de transacciones en Spring 1.2, está vez abordaré las diferencias de hacer la misma tarea en Spring 2.0. La mayor diferencia es que mientras que Spring 1.2 utilizaba Spring AOP que era muy limitado ya que sólo permitía programación orientada a aspectos a nivel de método, Spring 2.0 se integra perfectamente con AspectJ dando toda la potencia de la programación orientada a aspectos, pero facilitando la sintaxis. Es decir, Spring 2.0 propone programar los aspectos en AspectJ pero de manera declarativa, también ofrece la posibilidad de utilizar annotations tanto para definir aspectos como para realizar transacciones de manera declarativa. En este post abordaré como realizar transacciones de manera declarativa dejando el tema de los aspectos para otro post, a su vez tan sólo especificaré lo que cambia respecto a Spring 1.2 así que el que tenga dudas puede revisar este post. [...]

  • 2. Alberto  |  junio 7th, 2007 at 12:00 pm

    Hola lo que no veo es con esto de las transacciones delarativas no hace falta hacer el rollback en el código java?.

    o digo por que hice un ejemplo de 2 inserciones en un manager si la segunda peta por integridad de datos referenciados la primera inserta no debería hacer rollback. Lo he dejado como tu con el propagation_required

    Es decir solo se configura con esta declaración

  • 3. Raúl Vicente  |  junio 7th, 2007 at 1:00 pm

    Buenas Alberto, no veo tu código pero en principio si tu has puesto propagation required todo se ejecuta en la misma transacción de tal manera que si falla todo. Pero asegurate que las dos llamadas estén dentro del mismo método del facade porque si estas haciendo pruebas con Junit y lo haces en 2 métodos separados y haces un test para cada método te lo hace en 2 transacciones separadas, es decir, una por test y puede ser esa la naturaleza de tu problema.

    Un saludo.

  • 4. Dennis  |  octubre 9th, 2009 at 2:25 am

    Hola, yo estoy implementando struts y spring y en el aplicationcontext he seguido tu ejemplo, cuando ejecuto el proyecto no tengo ningun problema pero cuando me logueo me sale 2 errores (pero si quito el readOnly de : PROPAGATION_REQUIRED,readOnly la aplicacion responde pero no me trae datos desde la BD) Gracias por tu respuesta:
    PRIMER ERROR
    ————————————-
    javax.servlet.ServletException: org.springframework.jdbc.UncategorizedSQLException: SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [S1009]; error code [0];
    — The error occurred in com/spring/model/ibatis/xml/Usuario.xml.
    — The error occurred while applying a parameter map.
    — Check the Usuario.param.
    — Check the statement (update procedure failed).
    — Cause: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
    — The error occurred in com/spring/model/ibatis/xml/Usuario.xml.
    — The error occurred while applying a parameter map.
    — Check the Usuario.param.
    — Check the statement (update procedure failed).
    — Cause: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
    org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:535)
    org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:433)
    org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
    org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
    org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)

    ———————————————

    SEGUNDO ERRORR
    com.ibatis.common.jdbc.exception.NestedSQLException:
    — The error occurred in com/spring/model/ibatis/xml/Usuario.xml.
    — The error occurred while applying a parameter map.
    — Check the Usuario.param.
    — Check the statement (update procedure failed).
    — Cause: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

  • 5. Dennis  |  octubre 9th, 2009 at 4:40 am

    — The error occurred in com/spring/model/ibatis/xml/Usuario.xml.
    — The error occurred while applying a parameter map.
    — Check the Usuario.paramLogin.
    — Check the statement (update procedure failed).
    — Cause: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

  • 6. Dennis  |  octubre 9th, 2009 at 5:57 am


    {call proc_usuario_select(?,?)}

  • 7. Dennis  |  octubre 9th, 2009 at 5:58 am

    {call proc_usuario_select(?,?)}

  • 8. Dennis  |  octubre 9th, 2009 at 6:06 am

    pero si hago con un <select no tengo problemas pero yo necesariamente necesito ejecutar un store procedure

  • 9. Dennis  |  octubre 9th, 2009 at 6:07 am

    ERROR:

    { call proc_usuario_select(#strUsuario#,#strClave#) }

    NO ERROR:

    select * from usuario where usuario = #strUsuario# and clave = #strClave#

  • 10. Dennis  |  octubre 9th, 2009 at 6:07 am

    en primera instancia estaba poniendo lo asi:

Comenta el articulo:

Requerido

Requerido,