Gestión de transacciones declarativas de Spring

El enfoque de gestión declarativa de transacciones le permite gestionar la transacción con la ayuda de la configuración en lugar de la codificación en su código fuente. Esto significa que puede separar la gestión de transacciones del código comercial. Solo usa anotaciones o configuración basada en XML para administrar las transacciones. La configuración del bean especificará los métodos para ser transaccionales. Estos son los pasos asociados con la transacción declarativa:

  • Usamos la etiqueta <tx: advice />, que crea un aviso de manejo de transacciones y al mismo tiempo definimos un punto de acceso que coincide con todos los métodos que deseamos realizar transacciones y hace referencia al aviso transaccional.

  • Si se ha incluido un nombre de método en la configuración transaccional, el aviso creado comenzará la transacción antes de llamar al método.

  • El método de destino se ejecutará en un bloque try / catch .

  • Si el método finaliza normalmente, el aviso de AOP confirma la transacción correctamente; de ​​lo contrario, realiza una reversión.

Veamos cómo funcionan los pasos mencionados anteriormente, pero antes de comenzar, es importante tener al menos dos tablas de base de datos en las que podamos realizar varias operaciones CRUD con la ayuda de transacciones. Tomemos unStudent tabla, que se puede crear en la base de datos MySQL TEST con el siguiente DDL:

CREATE TABLE Student(
   ID   INT NOT NULL AUTO_INCREMENT,
   NAME VARCHAR(20) NOT NULL,
   AGE  INT NOT NULL,
   PRIMARY KEY (ID)
);

La segunda mesa es Marksen el que mantendremos calificaciones para los estudiantes en función de los años. aquíSID es la clave externa para la tabla Student.

CREATE TABLE Marks(
   SID INT NOT NULL,
   MARKS  INT NOT NULL,
   YEAR   INT NOT NULL
);

Ahora, escribamos nuestra aplicación Spring JDBC que implementará operaciones simples en las tablas Student y Marks. Tengamos un IDE de Eclipse en funcionamiento y sigamos los siguientes pasos para crear una aplicación Spring:

Paso Descripción
1 Cree un proyecto con un nombre SpringExample y cree un paquete com.tutorialspoint bajo elsrc carpeta en el proyecto creado.
2 Agregue las bibliotecas Spring requeridas usando la opción Agregar JAR externos como se explica en el capítulo Ejemplo de Spring Hello World .
3 Agregue otras bibliotecas necesarias mysql-connector-java.jar , aopalliance-xyjar , org.springframework.jdbc.jar y org.springframework.transaction.jar en el proyecto. Puede descargar las bibliotecas necesarias si aún no las tiene.
4 Cree la interfaz DAO StudentDAO y enumere todos los métodos necesarios. Aunque no es obligatorio y puede escribir directamente la clase StudentJDBCTemplate , pero como una buena práctica, hagámoslo.
5 Crear otras clases de Java necesarios StudentMarks , StudentMarksMapper , StudentJDBCTemplate y MainApp bajo la com.tutorialspoint paquete. Puede crear el resto de las clases POJO si es necesario.
6 Asegúrate de haber creado Student y Markstablas en la base de datos TEST. También asegúrese de que su servidor MySQL esté funcionando bien y que tenga acceso de lectura / escritura en la base de datos utilizando el nombre de usuario y la contraseña proporcionados.
7 Cree el archivo de configuración de Beans Beans.xml bajo elsrc carpeta.
8 El paso final es crear el contenido de todos los archivos Java y el archivo de configuración de Bean y ejecutar la aplicación como se explica a continuación.

A continuación se muestra el contenido del archivo de interfaz del objeto de acceso a datos StudentDAO.java

package com.tutorialspoint;

import java.util.List;
import javax.sql.DataSource;

public interface StudentDAO {
   /** 
      * This is the method to be used to initialize
      * database resources ie. connection.
   */
   public void setDataSource(DataSource ds);
   
   /** 
      * This is the method to be used to create
      * a record in the Student and Marks tables.
   */
   public void create(String name, Integer age, Integer marks, Integer year);
   
   /** 
      * This is the method to be used to list down
      * all the records from the Student and Marks tables.
   */
   public List<StudentMarks> listStudents();
}

A continuación se muestra el contenido de la StudentMarks.java archivo

package com.tutorialspoint;

public class StudentMarks {
   private Integer age;
   private String name;
   private Integer id;
   private Integer marks;
   private Integer year;
   private Integer sid;

   public void setAge(Integer age) {
      this.age = age;
   }
   public Integer getAge() {
      return age;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      return name;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   public Integer getId() {
      return id;
   }
   public void setMarks(Integer marks) {
      this.marks = marks;
   }
   public Integer getMarks() {
      return marks;
   }
   public void setYear(Integer year) {
      this.year = year;
   }
   public Integer getYear() {
      return year;
   }
   public void setSid(Integer sid) {
      this.sid = sid;
   }
   public Integer getSid() {
      return sid;
   }
}

A continuación se muestra el contenido de la StudentMarksMapper.java archivo

package com.tutorialspoint;

import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;

public class StudentMarksMapper implements RowMapper<StudentMarks> {
   public StudentMarks mapRow(ResultSet rs, int rowNum) throws SQLException {
      StudentMarks studentMarks = new StudentMarks();
      studentMarks.setId(rs.getInt("id"));
      studentMarks.setName(rs.getString("name"));
      studentMarks.setAge(rs.getInt("age"));
      studentMarks.setSid(rs.getInt("sid"));
      studentMarks.setMarks(rs.getInt("marks"));
      studentMarks.setYear(rs.getInt("year"));

      return studentMarks;
   }
}

A continuación se muestra el archivo de clase de implementación StudentJDBCTemplate.java para la interfaz DAO definida StudentDAO

package com.tutorialspoint;

import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

public class StudentJDBCTemplate implements StudentDAO {
   private JdbcTemplate jdbcTemplateObject;

   public void setDataSource(DataSource dataSource) {
      this.jdbcTemplateObject = new JdbcTemplate(dataSource);
   }
   public void create(String name, Integer age, Integer marks, Integer year){
      try {
         String SQL1 = "insert into Student (name, age) values (?, ?)";
         jdbcTemplateObject.update( SQL1, name, age);

         // Get the latest student id to be used in Marks table
         String SQL2 = "select max(id) from Student";
         int sid = jdbcTemplateObject.queryForInt( SQL2 );

         String SQL3 = "insert into Marks(sid, marks, year) " + "values (?, ?, ?)";
         jdbcTemplateObject.update( SQL3, sid, marks, year);
         System.out.println("Created Name = " + name + ", Age = " + age);
         
         // to simulate the exception.
         throw new RuntimeException("simulate Error condition") ;
      } 
      catch (DataAccessException e) {
         System.out.println("Error in creating record, rolling back");
         throw e;
      }
   }
   public List<StudentMarks> listStudents() {
      String SQL = "select * from Student, Marks where Student.id = Marks.sid";
      List <StudentMarks> studentMarks = jdbcTemplateObject.query(SQL, 
         new StudentMarksMapper());
      
      return studentMarks;
   }
}

Ahora pasemos al archivo principal de la aplicación. MainApp.java, que es como sigue

package com.tutorialspoint;

import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");

      StudentDAO studentJDBCTemplate = 
         (StudentDAO)context.getBean("studentJDBCTemplate");
      
      System.out.println("------Records creation--------" );
      studentJDBCTemplate.create("Zara", 11, 99, 2010);
      studentJDBCTemplate.create("Nuha", 20, 97, 2010);
      studentJDBCTemplate.create("Ayan", 25, 100, 2011);

      System.out.println("------Listing all the records--------" );
      List<StudentMarks> studentMarks = studentJDBCTemplate.listStudents();
      
      for (StudentMarks record : studentMarks) {
         System.out.print("ID : " + record.getId() );
         System.out.print(", Name : " + record.getName() );
         System.out.print(", Marks : " + record.getMarks());
         System.out.print(", Year : " + record.getYear());
         System.out.println(", Age : " + record.getAge());
      }
   }
}

A continuación se muestra el archivo de configuración Beans.xml

<?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:tx = "http://www.springframework.org/schema/tx"
   xmlns:aop = "http://www.springframework.org/schema/aop"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

   <!-- Initialization for data source -->
   <bean id="dataSource" 
      class = "org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name = "driverClassName" value = "com.mysql.jdbc.Driver"/>
      <property name = "url" value = "jdbc:mysql://localhost:3306/TEST"/>
      <property name = "username" value = "root"/>
      <property name = "password" value = "cohondob"/>
   </bean>
  
   <tx:advice id = "txAdvice" transaction-manager = "transactionManager">
      <tx:attributes>
      <tx:method name = "create"/>
      </tx:attributes>
   </tx:advice>
	
   <aop:config>
      <aop:pointcut id = "createOperation" 
         expression = "execution(* com.tutorialspoint.StudentJDBCTemplate.create(..))"/>
      
      <aop:advisor advice-ref = "txAdvice" pointcut-ref = "createOperation"/>
   </aop:config>
	
   <!-- Initialization for TransactionManager -->
   <bean id = "transactionManager"
      class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
      
      <property name = "dataSource" ref = "dataSource" />    
   </bean>

   <!-- Definition for studentJDBCTemplate bean -->
   <bean id = "studentJDBCTemplate"  
      class = "com.tutorialspoint.StudentJDBCTemplate">
      <property name = "dataSource" ref = "dataSource"/>  
   </bean>

</beans>

Una vez que haya terminado de crear los archivos de configuración de fuente y bean, ejecutemos la aplicación. Si todo está bien con su aplicación, imprimirá la siguiente excepción. En este caso, la transacción se revertirá y no se creará ningún registro en la tabla de la base de datos.

------Records creation--------
Created Name = Zara, Age = 11
Exception in thread "main" java.lang.RuntimeException: simulate Error condition

Puede probar el ejemplo anterior después de eliminar la excepción y, en este caso, debería confirmar la transacción y debería ver un registro en la base de datos.