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
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:
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; } }
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 }
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 }
Un post cortito de fin de semana 🙂 , este trata de la forma de extraer la información de una base de datos formar una es[...]
Si necesitamos mostrar gráficos estadísticos en nuestras aplicaciones android, contamos con muchas librerías disponibles[...]
Cuando Android estaba en sus inicios, varios IDEs (Entorno de Desarrollo Integrado) se disputaban el dominio por su de[...]
En este tutorial crearemos una sencilla aplicación para android que nos permitirá subir una imagen a un servidor web. La[...]
Tink es una biblioteca de cifrado desarrollada por un grupo de criptógrafos e ingenieros de seguridad de Google lanzado[...]
A veces navegando en la internet buscando novedades , investigando o simplemente perdiendo el tiempo 🙂 se encuentran cos[...]