You are on page 1of 10

Captulo IV Transacciones

Las transacciones juegan un rol importante en el desarrollo de software, nos aseguran que los datos nunca van a estar en un estado incosistente, por lo tanto una transaccin puede ser concebida como el conjunto de operaciones a ejecutar; si todas son exitosas la transaccin sern exitosa, pero si alguna falla, la transaccin se anular por completo. 4.1. Caractersticas. Cuatro palabras definen las caractersticas de una transaccin, a saber: Atmica. Una transaccin esta compuesta por una ms actividades concebidas como una sola unidad de trabajo. La atomicidad asegura que todas las operaciones de la transaccin se ejecutan o no se ejecutan. Consistente. Una transaccin se considera consistente cuando al finalizar (satisfactoriamente o no), los datos permanecen estables. Aislada (Isolated). Las transacciones normalmente permiten que uno o varios usuarios puedan acceder a los datos al mismo tiempo, evitando que un usuario pueda afectar el trabajo de otro: Bloqueo de registros y/o tablas. Durable. Una vez que una transaccin finaliza el resultado de la misma debe ser permanente en la base de datos y sobrevivir a posibles cadas del sistema.

4.2. Seleccionando un gestor de transacciones. Una aplicacin tpica Java que utiliza JDBC cmo mtodo de persistencia de informacin, puede definir implementar un manejo transaccional en sus operaciones tal como observamos en la siguiente figura: public void comprar (String codigo, String usuario) { Connection conn = null; try { conn = dataSource.getConnection(); conn.setAutoCommit(false); conn.commit(); } catch (SQLException e) { if (conn != null) { try { conn.rollback(); }catch (SQLException e1){ }

} . } finally { } } Un gestor de transacciones es el encargado de asegurar las caractersticas de una transaccin: Atomicidad, Durabilidad y Aislamiento. En caso de error en la ejecucin de la transaccin la base de datos debe volver a su estado anterior. Existen en el mercado un sinnmero de gestores de transacciones dependiendo de la tecnologa a utilizar para lograr la persistencia de datos, Spring ofrece a travs de la interface PlatformTransactionManager la posibilidad de utilizar diversos gestores de transacciones dependiendo de nuestras necesidades.

4.3. Transacciones en J2ee. Las transacciones en J2ee normalmente son gestionadas por el Java Transaction Service (JTS) en conjunto con el Java Transaction Api (JTA). Aqu se definen cinco tipos de actores a mencionar: Un Gestor de Transacciones, responsable de la demarcacin, gestin de recursos, sincronizacin y propagacin de las transacciones. Un Gestor de Recursos que provee acceso a recursos transacciones, por ejemplo: servidor de base de datos, de mensajera, etc. Un Servidor de Aplicaciones, que provee el entorno de ejecucin para las aplicaciones y gestiona el estado de las transacciones. Una Aplicacin que opera normalmente en un servidor de aplicaciones. Un Gestor de Comunicaciones, que facilita la propagacin de la transaccin entre mltiples gestores de transacciones.

<bean id=transactionManager class=org.springframework.jdbc.datasource. DataSourceTransactionManager> <property name =dataSource ref=dataSource/> </bean> Fig. Declaracin de un transaction manager JDBC. <bean id=transactionManager class=org.springframework.transaction.jta. JtaTransactionManager> <property name =transactionManagerName value=java:/TransactionManager/> </bean> Fig. Declaracin de un transaction manager JTA. 4.3.1. Tipos de Transacciones. Las transacciones pueden ser clasificadas en dos tipos en funcin a nuestras necesidades: a) Transacciones Locales. Si nuestra aplicacin slo involucra a un simple gestor de recursos transaccionales (bases de datos, mensajera, etc), entonces estamos al frente de una transaccin local, por ejemplo, gestionamos las transacciones via JDBC, todo lo que necesitamos es definir previamente la siguiente lnea: conn.setAutoCommit(false); b) Transacciones Globales. Una transaccin global tpicamente involucra mltiples gestores de recursos y gestores de transacciones que deben coordinar entre ellos para definir si la transaccin es exitosa o no. Las transacciones globales normalmente se basan en el protocolo two-phase commit, lo que significa que la primera fase consiste en solicitar a todos los recursos involucrados que se preparen para la ejecucin de un commit; si la primera fase se completa y todos los recursos estn listos para la ejecucin del commit, entonces la segunda fase continua ejecutndose el commit de todos los cambios realizados. Si algn recurso falla en la preparacin de la primera fase, entonces todos los recursos debern deshacer (rollback) todos los cambios durante la segunda fase. 4.3.2. Demarcacin de las Transacciones. Sin importar si utilizamos transacciones locales globales, debemos siempre indicarle al gestor de transacciones cundo la transaccin inicia y cuando finaliza; esto es conocido como demarcacin de la transaccin y existen actualmente dos maneras de realizarlo: programticamente a travs de JTA JDBC declarativamente tal cmo nos lo ofrece un contenedor EJB un marco de trabajo como Spring (JTA).

4.3.2.1. Gestin Programtica de la Transaccin.

Tpicamente los programadores tienen la posibilidad de indicar el inicio, la confirmacin o cancelacin de una transaccin en el cdigo de la aplicacin. Esto reduce las opciones de un futuro reuso del cdigo. 4.3.2.2. Transacciones Declarativas. Las transacciones declarativas ofrecen una alternativa atractiva a la opcin programtica, dado que el cdigo no se involucra en la demarcacin de la transaccin dejando esta responsabilidad al marco de trabajo. Este tipo de definicin de las transacciones hace mucho tiempo era una caracterstica disponible slo en contenedores EJB. Actualmente Spring ofrece soporte para su uso en POJOs. Un punto importante a mencionar con esta forma de demarcacin de la transaccin es el comportamiento de la propagacin de la transaccin la cual define los lmites de la transaccin respecto al cliente y al mtodo invocado. Spring define siete (07) tipos de propagacin siendo la propagacin por defecto la definida como: PROPAGATION_REQUIRED; a continuacin observamos los siguientes tipos: PROPAGATION_REQUIRED. Indica que el mtodo actual debe ejecutarse como parte de una transaccin. Si una transaccin estuviese en proceso, el mtodo se ejecutar en dicha transaccin caso contrario se crear una nueva. PROPAGATION_SUPPORTS. Indica que el mtodo actual no necesita una transaccin en caso no la necesite, caso contrario se ejecuta dentro de una transaccin. PROPAGATION_MANDATORY. Indica que el mtodo debe ejecutarse dentro de una transaccin, si esta no existe se origina una excepcin. PROPAGATION_REQUIRES_NEW. Indica que el mtodo actual debe se ejecutado dentro de su propia transaccin. Una nueva transaccin se inicia en caso que exista una en progreso, la cual es suspendida mientras dure la ejecucin del mtodo. PROPAGATION_NOT_SUPPORTED. Indica que el mtodo actual no debe ser ejecutado dentro de una transaccin, en caso que exista una transaccin en proceso, la misma es suspendida mientras dure la ejecucin del mtodo. PROPAGATION_NEVER. Indica que el mtodo actual no debe ser ejecutado en un contexto transaccional. En caso que exista una transaccin en proceso, una excepcin es lanzada.

PROPAGATION_NESTED. Indica que el mtodo actual debe ser ejecutado en una transaccin anidada si es que una transaccin ya se encuentra en proceso. La

transaccin anidada puede ser confirmada deshecha individualmente caso contrario se acta segn lo indicado en PROPAGATION_REQUIRED.

Fig. Declaracin de una transaccin 4.4. Formas de implementacin de las transacciones. a) Gestin programtica utilizando el Transaction Manager API. public class TestJdbc extends NamedParameterJdbcDaoSupport { private String sql = "insert into persona (Id, Nombres, Apellidos) values (:id, :nombres, :apellidos)"; private PlatformTransactionManager transactionManager; public void saveMotorist (PersonaBean persona) { TransactionDefinition def = new DefaultTransactionDefinition(); TransactionStatus status = transactionManager.getTransaction(def); try { Map parameters = new HashMap(); parameters.put("id", persona.getId());

parameters.put("nombres", persona.getNombres()); parameters.put("apellidos", persona.getApellidos()); getNamedParameterJdbcTemplate().update (sql2, parameters); transactionManager.commit(status); }catch(DataAccessException e){ System.out.println("Rollback"); transactionManager.rollback(status); } } /** * @return the transactionManager */ public PlatformTransactionManager getTransactionManager() { return transactionManager; } /** * @param transactionManager the transactionManager to set */ public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionManager = transactionManager; } } Fig. Utilizando un TransactionManager. A continuacin observemos como queda nuestro fichero applicationContext.xml: <bean id="testJdbc" class="com.spring.myjdbc.TestJdbc"> <property name="dataSource" ref="dataSource"/> <property name="transactionManager" ref="transactionManager"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="sun.jdbc.odbc.JdbcOdbcDriver"/> <property name="url" value="jdbc:odbc:SpringODBC"/> <property name="username" value=""/> <property name="password" value=""/> </bean>

Fig. applicationContext.xml b) Gestin programtica utilizando el Transaction Template. public class TestJdbc extends NamedParameterJdbcDaoSupport { private String sql = "insert into persona (Id, Nombres, Apellidos) values (:id, :nombres, :apellidos)"; private TransactionTemplate transactionTemplate; public void saveMotorist (final PersonaBean persona) { transactionTemplate.execute(new TransactionCallbackWithoutResult(){ protected void doInTransactionWithoutResult(TransactionStatus status){ Map parameters = new HashMap(); parameters.put("id", persona.getId()); parameters.put("nombres", persona.getNombres()); parameters.put("apellidos", persona.getApellidos()); getNamedParameterJdbcTemplate().update (sql2, parameters); } }); } /** * @return the transactionTemplate */ public TransactionTemplate getTransactionTemplate() { return transactionTemplate; } /** * @param transactionTemplate the transactionTemplate to set */ public void setTransactionTemplate(TransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } } Fig. Utilizando un TransactionTemplate.

<bean id="testJdbc" class="com.spring.myjdbc.TestJdbc"> <property name="dataSource" ref="dataSource"/> <property name="transactionTemplate" ref="transactionTemplate"/> </bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="sun.jdbc.odbc.JdbcOdbcDriver"/> <property name="url" value="jdbc:odbc:SpringODBC"/> <property name="username" value=""/> <property name="password" value=""/> </bean> Fig. applicationContext.xml c) Gestionar transacciones declarativamente con Transaction Advices. public class TestJdbc extends NamedParameterJdbcDaoSupport implements DaoTest { private String sql = "insert into persona (Id, Nombres, Apellidos) values (:id, :nombres, :apellidos)"; public void saveMotorist (PersonaBean persona) { Map parameters = new HashMap(); parameters.put("id", persona.getId()); parameters.put("nombres", persona.getNombres()); parameters.put("apellidos", persona.getApellidos()); getNamedParameterJdbcTemplate().update (sql, parameters); } } Fig. Utilizando Transaction Advices. (Incluir aspectjwaver, aopalliance, aspect.jar) <tx:advice id="MyAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="saveMotorist"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="MyAop" expression="execution(* com.spring.myjdbc.*.*(..))"/>

<aop:advisor advice-ref="MyAdvice" pointcut-ref="MyAop"/> </aop:config> <bean id="testJdbc" class="com.spring.myjdbc.TestJdbc"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="sun.jdbc.odbc.JdbcOdbcDriver"/> <property name="url" value="jdbc:odbc:SpringODBC"/> <property name="username" value=""/> <property name="password" value=""/> </bean> Fig. applicationContext.xml d) Gestionar transacciones declarativamente con la anotacin @Transactional @Transactional public void saveMotorist (PersonaBean persona, CursoBean curso) { Map parameters2 = new HashMap(); parameters2.put("codigo", curso.getCodigo()); parameters2.put("descripcion", curso.getDescripcion()); parameters2.put("codigop", "001"); getNamedParameterJdbcTemplate().update (sql3, parameters2); Map parameters3 = new HashMap(); parameters3.put("codigo", "002"); parameters3.put("descripcion", "Curso2"); parameters3.put("codigop", "001"); getNamedParameterJdbcTemplate().update (sql3, parameters3); } Fig. Utilizando anotaciones.

<tx:annotation-driven transaction-manager="transactionManager"/> <bean id="testJdbc" class="com.spring.myjdbc.TestJdbc"> <property name="dataSource" ref="dataSource"/>

</bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="sun.jdbc.odbc.JdbcOdbcDriver"/> <property name="url" value="jdbc:odbc:SpringODBC"/> <property name="username" value=""/> <property name="password" value=""/> </bean> Fig. applicationContext.xml

You might also like