http://static.springsource.
Conceptualmente una transacción luce como la imagen aqui arriba pero vamos a describir un poco mas el detalle.
Primeramente necesitamos la dependencia de spring-aspects, considerando que nuestro proyecto sea maven, debemos agregar a nuestro pom.xml la siguiente dependencia (por ahora usaremos la ón 2.5.6):
<dependency> <groupid>org.springframework</groupid> <artifactid>spring-aspects</artifactid> <version>2.5.6</version> </dependency>
Basicamente necesitamos configurar tres elementos, (1) el manejador de las transacciones y su fuente de datos o DataSource, (2) un advice que es el código a ejecutar antes y/o despues de una petición a la base de datos punto central para iniciar-propagar-terminar una transaccion, y finalmente (3) un advisor, que es la relación de dicho advice con un pointcut.
1.- Manejador de transacciones (TransactionManager)
Como nuestro manejador de transacciones requiere de una fuente de datos vamos a configurarla con un driver de mysql de la siguiente forma de momento pues no abundaremos en la configuracion del datasource:
<bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost/miBaseDatos"/> <property name="username" value="user_sa"/> <property name="password" value="mipass_sa"/> </bean>
Luego necesitamos escoger una estrategia de transaccionalidad que implemente la interface de spring org.springframework.
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="basicDataSource"/> </bean>
2.- Advice
Lo que sigue es configurar el advice o la forma en que se va a manejar la transaccionalidad, para ello necesitamos agregar el esquema y el esquema location de transaccion a nuestro tag
- xmlns:tx="http://www.
springframework.org/schema/tx" - xsi:schemaLocation="http://
www.springframework.org/ schema/tx http://www.springframework. org/schema/tx/spring-tx-2.5. xsd"
<tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <!-- todos los metodos que inicien con get van a ser de solo lectura --> <tx:method name="get*" read-only="true"/> <!-- todos los metodos que inicien con guardar van a ejecutar rollback si se lanza alguna error de estos tipos--> <tx:method name="guardar*" rollback-for="java.sql.SQLException, x.y.MiInfraestructuraException"/> <!-- cualquier otro metodo usara la configuracion por defecto de una transaccion--> <tx:method name="*"/> </tx:attributes> </tx:advice>
Ojo: si tu bean manejador de transacciones ya se llama "transactionManager", puedes omitir la propiedad transaction-manager de tx:advice.
Es importante mencionar que por definición, Spring realiza rollback si encuentra que fue lanzada una Exception que herede de RuntimeException (osea no checadas) y las que listemos mediante la propiedad rollback-for. Esta propiedad nos ayuda a identificar las excepciones de negocio propias que deben provocar un rollback en la base de datos.
3.- Advisor y Pointcut
Finalmente vamos a asegurarnos que el comportamiento que acabamos de definir para nuestras transacciones sea ejecutado para cualquier operación definida mediante un aop:pointcut, para eso usamos un advisor. Agregamos el esquema y el esquema location de aop nuestro tag
- xmlns:aop="http://www.
springframework.org/schema/aop " - xsi:schemaLocation="http://
www.springframework.org/ schema/aop http://www.springframework. org/schema/aop/spring-aop-2.5. xsd"
Con un aop:advisor simplemente relacionamos el pointcut con el advice previamente definido.
<aop:config> <aop:pointcut id="operacionesDeServicios" expression="execution(* x.y.service.*Service.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="operacionesDeServicios"/> </aop:config>
Nota1:
La sintaxis para el comando AspectJ execution es como sigue. Puedes usar ' * ' para indicar "todos", o bien '..' (dos puntos seguidos) para indicar "este paquete o uno más interno", o bien, "más argumentos" si el caso del método:
execution([valorRetornoDelMeto do] [paquete].[clase].[nombreMetod o]([listaArgumentos]))
Ejemplo: Todos los métodos que empiecen con guardar que devuelvan void y reciban por lo menos un long que pertenezcan a las clases que terminen con Dao y sean del paquete x.y.daos o subpaquetesexecution (void x.y.daos..*Dao.guardar*(long.. ))
Para entender un poco mas sobre las expresiones de aspectJ ve la referencia de aop-aspectj.Ejemplo: Todos los métodos que empiecen con guardar que devuelvan void y reciban por lo menos un long que pertenezcan a las clases que terminen con Dao y sean del paquete x.y.daos o subpaquetes
Nota 2: Para no confundirnos con los esquemas, la definición del tag
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- todos los demas beans que vimos--> </beans>
Referencias:
Muy buena , me ayudo bastante
ResponderEliminar