Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube
JC Mouse Bolivia
Index / Java / Transacciones – Uso de Commit y Rollback

Transacciones – Uso de Commit y Rollback

Autor jc mouse martes, abril 7, 2015

Cuando desarrollamos aplicaciones en java con base de datos debemos tener cuidado en que se cumplan un conjunto de características conocida como ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad), en el caso de este post nos centraremos en la Atomicidad y Consistencia

Atomicidad: es la propiedad que asegura que la operación se ha realizado o no, y por lo tanto ante un fallo del sistema no puede quedar a medias. Se dice que una operación es atómica cuando es imposible para otra parte de un sistema encontrar pasos intermedios. Si esta operación consiste en una serie de pasos, todos ellos ocurren o ninguno. Por ejemplo, en el caso de una transacción bancaria o se ejecuta tanto el depósito como la deducción o ninguna acción es realizada. [Wikipedia]
Consistencia: Integridad. Es la propiedad que asegura que sólo se empieza aquello que se puede acabar. Por lo tanto se ejecutan aquellas operaciones que no van a romper las reglas y directrices de integridad de la base de datos. La propiedad de consistencia sostiene que cualquier transacción llevará a la base de datos desde un estado válido a otro también válido. «La Integridad de la Base de Datos nos permite asegurar que los datos son exactos y consistentes, es decir que estén siempre intactos, sean siempre los esperados y que de ninguna manera cambien ni se deformen. De esta manera podemos garantizar que la información que se presenta al usuario será siempre la misma.» [Wikipedia]

Planteando una situación para este tutorial

Si tenemos una serie de sentencias SQL INSERT por ejecutar y por un motivo XYZ 🙂 surge un error que no permite que se completen todas estas sentencias nos encontramos con el problema de que hasta el punto que se produjo el error, los INSERT se ejecutaron y se guardaron nuevos registros en la base de datos, entonces estaríamos violando los criterios de Atomicidad y de Consistencia porque no primeramente no se completo la transacción en su totalidad pero tenemos nuevos registros en la base de datos pero estos registros están incompletos.

¿Como podemos solucionar este problema?

Necesitamos

  • Java
  • IDE Netbeans 7.x o Eclipse
  • Libreria MySQL JDBC Driver
  • MySQL

Nivel: Intermedio

Tiempo. 15 minutos

Base de datos.

Para el ejemplo de este post, utilizaremos dos tablas «miTabla» y «miOtraTabla«, su estructura es la siguiente:

-- 
-- Estructura de tabla para la tabla 'mitabla'
-- 

CREATE TABLE mitabla (
  DNI varchar(12) default NULL,
  correo varchar(32) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 
-- Estructura de tabla para la tabla 'miotratabla'
-- 

CREATE TABLE miotratabla (
  nombre varchar(20) default NULL,
  apellido varchar(20) default NULL,
  edad int(20) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

IMPORTANTE al crear las tablas, debemos utilizar ENGINE=InnoDB y no MyISAM esto porque InnoDB tiene soporte para transacciones, bloqueo de registros y nos permite tener las características ACID  garantizando la integridad de nuestras tablas.

Proyecto Netbeans

Nuestro proyecto base sera el siguiente:

rollback commit

  • Le añadimos el conector JDBC al proyecto
  • Tenemos una clase llamada Database.java que nos permite conectarse a la base de datos MySQL
  • Tenemos dos clases Main, JNoRollback y JRollback, en la primera clase se implementara las instrucciones INSERT sin el uso de Commit y Rollback , en la segunda clase con el uso de estos 2 métodos, el fin es apreciar mejor que pasa cuando se produce un error al ejecutar estas transacciones.
Clase Database.java
package app;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
 * @web https://www.jc-mouse.net/
 * @author Mouse
 */
public class Database {

   private final static String bd = "BASE_DE_DATOS";
   private final static String login = "USUARIO";
   private final static String password = "CONTRASEÑA";
   private final static String url = "jdbc:mysql://localhost/"+bd;

    public static Connection getConnection(){
        try{
         Class.forName("com.mysql.jdbc.Driver");         
         Connection conn = DriverManager.getConnection(url,login,password);
         if (conn!=null){
            System.out.println("Conectado a la base de datos ["+bd+"]");
         }
         return conn;
      }catch(SQLException e){
         System.err.println(e.getMessage());
      }catch(ClassNotFoundException e){
         System.err.println(e.getMessage());
      }
      return null;
   }

}
Clase JNoRollback.java
En esta clase no se hace uso de los métodos Commit y RollBack por lo que las instrucciones INSERT se irán ejecutando una tras otra afectando directamente a la base de datos, si no se encontrara ningún error todo terminaría normalmente, sin embargo en la linea de código 46 intencionalmente se intercambia el tipo de dato INT por un STRING  esto para provocar una excepción, entonces las instrucciones INSERT de las lineas 30,35,40 se ejecutaran pero no así la linea 47.
01 package app;
02 import java.sql.Connection;
03 import java.sql.PreparedStatement;
04 import java.sql.SQLException;
05 /**
06  * @web https://www.jc-mouse.net/
07  * @author Mouse
08  */
09 public class JNoRollback {
10 
11     /**
12  * @param args the command line arguments
13  */
14     public static void main(String[] args) {
15         
16          //Obtenemos conexion a la base de datos
17         Connection connection = Database.getConnection();
18          
19         PreparedStatement stmt1=null;
20         PreparedStatement stmt2=null;         
21         
22         try {            
23             //Se preparan las sentencias SQL
24             stmt1 = connection.prepareStatement("INSERT INTO miTabla VALUES( ?, ? );");            
25             stmt2 = connection.prepareStatement("INSERT INTO miOtraTabla VALUES( ?, ?, ? );");
26             
27             System.out.println( "Primer INSERT tabla [miTabla] " ); 
28             stmt1.setString(1, "000001");
29             stmt1.setString(2, "micorreo@mail.com");
30             stmt1.executeUpdate();
31         
32             System.out.println( "Segundo INSERT tabla [miTabla] " ); 
33             stmt1.setString(1, "000002");
34             stmt1.setString(2, "amayuya@mail.com");
35             stmt1.executeUpdate();
36             
37             System.out.println( "Tercer INSERT tabla [miTabla] " ); 
38             stmt1.setString(1, "000003");
39             stmt1.setString(2, "diosdado@mail.com");
40             stmt1.executeUpdate();
41             
42             System.out.println( "Primer INSERT tabla [miOtraTabla]" );
43             stmt2.setString(1, "Juan");
44             stmt2.setString(2, "Perez");            
45             //stmt2.setInt(3, 99); //Tipo de dato CORRECTO INT
46             stmt2.setString(3, "Hola soy un error");//Tipo de dato INCORRECTO 
47             stmt2.executeUpdate();
48       
49         } catch (SQLException ex) {
50             System.err.println("ERROR: " + ex.getMessage());                            
51         }finally{
52             System.out.println( "cierra conexion a la base de datos" );    
53             try {
54                 if(stmt1!=null) stmt1.close();                
55                 if(stmt2!=null) stmt2.close();                
56                 if(connection!=null) connection.close();
57             } catch (SQLException ex) {
58                 System.err.println( ex.getMessage() );    
59             }
60         }      
61         
62     }//end:main
63 }
Ejecutando la clase Main JNoRollback obtenemos el siguiente resultado por consola:
mal
Como dijimos más arriba, al ejecutar este código se produce una excepción «ERROR: Incorrect integer value: ‘Hola soy un error’ for column ‘edad’ at row 1» y si revisamos la base de datos, podremos observar como en la tabla «miTabla» se registraron 3 nuevas filas pero si abrimos la tabla «miOtraTabla» no existen registros, es decir no se esta cumpliendo con lo principio de ATOMICIDAD Y CONSISTENCIA
Clase JRollback.java
Este clase contiene el mismo código de más arriba pero se le agrego algunas lineas de código extra
01 package app;
02 
03 import java.sql.Connection;
04 import java.sql.PreparedStatement;
05 import java.sql.SQLException;
06 /**
07  * @web http://jc-mouse.net/
08  * @author Mouse
09  */
10 public class JRollback {
11     
12     public static void main(String[] args) {
13 
14         //Obtenemos conexion a la base de datos
15         Connection connection = Database.getConnection();
16          
17         PreparedStatement stmt1=null;
18         PreparedStatement stmt2=null;         
19         
20         try {
21             //se deshabilita el modo de confirmación automática
22             connection.setAutoCommit(false);            
23             //Se preparan las sentencias SQL
24             stmt1 = connection.prepareStatement("INSERT INTO miTabla VALUES( ?, ? );");            
25             stmt2 = connection.prepareStatement("INSERT INTO miOtraTabla VALUES( ?, ?, ? );");
26             
27             System.out.println( "Primer INSERT tabla [miTabla] " ); 
28             stmt1.setString(1, "000001");
29             stmt1.setString(2, "micorreo@mail.com");
30             stmt1.executeUpdate();
31         
32             System.out.println( "Segundo INSERT tabla [miTabla] " ); 
33             stmt1.setString(1, "000002");
34             stmt1.setString(2, "amayuya@mail.com");
35             stmt1.executeUpdate();
36             
37             System.out.println( "Tercer INSERT tabla [miTabla] " ); 
38             stmt1.setString(1, "000003");
39             stmt1.setString(2, "diosdado@mail.com");
40             stmt1.executeUpdate();
41             
42             System.out.println( "Primer INSERT tabla [miOtraTabla]" );
43             stmt2.setString(1, "Juan");
44             stmt2.setString(2, "Perez");            
45             //stmt2.setInt(3, 99); //Tipo de dato CORRECTO INT
46             stmt2.setString(3, "Hola soy un error");//Tipo de dato INCORRECTO
47             stmt2.executeUpdate();
48             
49             //se indica que se deben aplicar los cambios en la base de datos
50             connection.commit();
51       
52         } catch (SQLException ex) {
53             System.err.println("ERROR: " + ex.getMessage());
54             if(connection!=null)
55             {
56                 System.out.println("Rollback");
57                 try {
58                     //deshace todos los cambios realizados en los datos
59                     connection.rollback();
60                 } catch (SQLException ex1) {
61                     System.err.println( "No se pudo deshacer" + ex1.getMessage() );    
62                 }
63             }                
64         }finally{
65             System.out.println( "cierra conexion a la base de datos" );    
66             try {
67                 if(stmt1!=null) stmt1.close();                
68                 if(stmt2!=null) stmt2.close();                
69                 if(connection!=null) connection.close();
70             } catch (SQLException ex) {
71                 System.err.println( ex.getMessage() );    
72             }
73         }      
74         
75     }//end:main
76 }
Explicación:
22 : Se deshabilita el modo de confirmación automática, es decir todas las instrucciones SQL a partir de ese punto se agrupan en una sola transacción que finalizara con una llamada al método commit o al método rollback.
45 : Este es el tipo de dato correcto que acepta la instrucción SQL, para usarlo des-comenta y comenta la linea de código 46
46 : El error de tipo de dato es el mismo que de la clase anterior
50 :  Aquí hacemos uso del método commit(), es decir si se llega hasta este punto quiere decir que no se encontró ningún error y por tanto todas las instrucciones SQL (en este caso INSERT) serán confirmadas.
59 : Si se produce alguna excepción, se hará un llamado al método rollback() este método deshace todos los cambios realizados en la transacción actual y libera cualquier bloque en la base de datos que contenga en esos momentos este objeto
 64 : Para terminar se cierra la conexión actual a la base de datos
Ejecutando esta clase obtenemos la siguiente salida en pantalla:
transaccion
Como en el caso anterior provocamos una excepción, sin embargo en esta oportunidad  la transacción no llega a ser confirmada (commit) y es anulada por el método rollback. Si nos fijamos en nuestra base de datos, veremos que tanto en la tabla «miTabla» y «miOtraTabla» no se registro nada.
Descarga el proyecto AQUI
🙂

Tags

Si te ha gustado podrías compartirlo o dejar un comentario. ¡Muchas gracias!
Autor: JC Mouse

Yo soy yo :) JC Mouse, Soy orgullosamente boliviano soy fundador y CEO de la web jc-Mouse.net uno de las pocas web en emprendimiento y tecnología en Bolivia.

Toda la información que encuentres en este sitio es y sera completamente gratis siempre, puedes copiar, descargar y re-publicar si así lo deseas en otros blogs o sitios web, solo te pido a cambio que dejes una referencia a esta web. Esto nos ayuda a crecer y seguir aportando. Bye

Enjoy! :)

También Te Podría Interesar

NBANDROID-V2 plugin para Netbeans

NBANDROID-V2 plugin para Netbeans

Cuando Android estaba en sus inicios, varios IDEs (Entorno de Desarrollo Integrado​​) se disputaban el dominio por su de...

CODOTA: Programación Inteligente

CODOTA: Programación Inteligente

La Inteligencia Artificial (AI – Artificial Intelligence) estará presente en casi cada aspecto de nuestra vida en...

JTable editable con base de datos

JTable editable con base de datos

JTable es un componente swing java que nos permite mostrar datos en una tabla de una base de datos, sin embargo a difere...

Botón en java de Windows 8 Modern UI

Botón en java de Windows 8 Modern UI

En este tutorial crearemos un botón con el estilo del nuevo windows 8 Modern UI que primero se conoció como Metro UI.  E...

Exportar registros MySQL a Excel

Exportar registros MySQL a Excel

Java Excel API es un API para java que permite a los desarrolladores leer y escribir en hojas de cálculo Excel. jexcelap...

Impresión de reportes

Impresión de reportes

Existen diferentes métodos par imprimir reportes hechos con JasperReport en aplicaciones hechas en java, en este post te...

4 comentarios en “Transacciones – Uso de Commit y Rollback”

  1. Oscar dice:

    Muy bueno, Mouse. Gracias por el esfuerzo de publicar lo que sabes.

  2. manuel dice:

    Jc, un consulta como haces en JAVA para usar el begin o el start transaction de la sintaxis de mysql server?

  3. rediespinoza dice:

    exceletente forma de explicar el manejo de las transciones muchas gracias

  4. Rances dice:

    Hey gracios por la explicación y el codigo me fue de gran ayuda 😀

Los comentarios estan cerrados

Comparte lo que sabes

Categorias

Últimas entradas

Por lo general se usan transacciones a nivel base de datos y posteriormente se llaman estos a través de procedimientos a...

En este post, aprenderemos como conectar Visual Basic 6 con SQL Server, abrir una tabla, leer su contenido y mostrar est...

Lo que veremos en este post es la configuración del driver para PHP de SQL Server que ha creado Microsoft el cual permit...

Google Bard la inteligencia artificial de Google se actualiza con una mejora que entra a competir con el resto de IAs y...

Herramientas

Generador de Enlaces a Whatsapp