No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Java SE: SQL y Bases de Datos

Curso de Java SE: SQL y Bases de Datos

Ana Fernanda Gutierrez Villanueva

Ana Fernanda Gutierrez Villanueva

Implementando transacciones con JDBC

16/22
Recursos
  1. Para agrupar varias sentencias en una única transacción, debes cambiar la propiedad “autocommit” de la conexión a “false”. Por defecto, esta propiedad está establecida en “true”. Al desactivar el “autocommit”, las sentencias no se ejecutarán de forma inmediata en la base de datos, lo que nos permite realizar varias operaciones en conjunto.
  2. Si todas las sentencias dentro de la transacción se completan sin errores, se realiza un “commit” al final de la transacción. El “commit” confirma los cambios y los guarda de manera permanente en la base de datos.
  3. Sin embargo, si ocurre alguna falla durante la ejecución de alguna sentencia dentro de la transacción, debes realizar un “rollback”. El “rollback” deshace todos los cambios realizados en la transacción, restaurando el estado anterior de la base de datos. Este paso se realiza dentro de un bloque catch, donde se capturan las excepciones.

Aportes 16

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Creo que asi no este dentro de una transaccion, si no se cumple los constraints, igual no guarda

El caso de uso no me gusto tanto, porque igualmente sin haber agregado el cambio al código, no se hubiese agregado el registro. Quizas lo interesante seria un ejemplo en donde se tengan varios registros, y no se inserte ninguno si alguno tiene el mismo curp, o un ejemplo en donde el registro se hubiese insertado en la bd si no se hubiera cacheado previamente.
Yo realice la implementacion en el databaseConection, implemente una funcion para salvar la transaccion y lo llamo desde el front cuando ya tengo todas las transacciones: ![](https://static.platzi.com/media/user_upload/image-e740809f-f79e-4906-985c-2b8c699d524c.jpg)
Otra forma de controlar las transacciones es con un Stored procedure. Si todo ok -> COMMIT sino -> ROLLBACK
Este fue un ejemplo pésimo, yo vengo de otros lenguaje de programación. ella no necesitaba commit ni rollback para que se cumpliera ya que al intentar insertar, la base de datos iba a gritar ya que ella le tenia el constrain único (UNIQUE) y el catch iba a devolver el mensaje. un buen ejemplo seria en una transaccion bancaria donde primero a la cuenta origen vas hacer un update para restar a la cuenta origen y un update para sumer el monto de la transaccion a la cuenta destino. errores que pude solventar el commit y rollback: 1 si se pierde la conexion en el primer update, no se aplica el commit. 2. si la cuenta destino tiene un bloqueo que no acepta transaccion ya sea porque es una cuenta cancelada o embargada entonces se aplica el commit. en su explicación ella puede quietar el commit y rollback y como quiera o va a persistir la información. 👎👎👎👎
No sé si soy el único, pero siento que se pierde mucho tiempo cuando va diciendo en voz alta lo que está escribiendo, en lugar de enfocarse más en el por qué de cada cosa. Además, sería útil que explicara mejor los métodos que utiliza. Por ejemplo, en el caso del método *rollback()*, sería bueno detenerse un momento para explicar en detalle cómo funciona y qué hace. De lo contrario, da la sensación de que solo se está copiando y pegando código sin profundizar en su propósito.
Extendiendo un poco para los que creen que el ejercicio no es el adecuado. El ejemplo no esta mal. En este caso esta inconclusa la explicación. Básicamente el try donde se hace la creación de un nuevo empleado es una transacción. En ella puedes hacer múltiples peticiones usando una sola conexión. Para que puedas comprobar que el principio atomic se cumple puedes crear dos nuevos empleados en el mismo try, el cual se maneja mediante una sola conexión. En mi caso estoy creando un Usuario pero pueden replicar el ejemplo usando la clase Employee de la clase: 1. Crea dos empleados nuevos. En mi caso son usuarios. En mi base de datos tengo como valores unicos los correos que es la misma restricción del curp de la clase: `User user1 = new User();` `user1.setNickname("Architect");` `user1.setPassword("admin123");` `user1.setLogin("logead");` `user1.setEmail("[email protected]");` `user1.setNickname("DevOps");` `User user2 = new User();` `user2.setNickname("AWS");` `user2.setPassword("admin123");` `user2.setLogin("logead");` `user2.setEmail("[email protected]");` `user2.setNickname("DevOps");` `List<User> usersList;` 1. Para ver los cambios dentro del try anidado intenta crear dos usuarios con el mismo curp. En primera instancia se crea el primer Employee pero el segundo tiene un error el roleBack elimina este cambio de la Base de datos. Que es el principio de atomicidad que se busca explicar con las transacciones. 2. Puedes comprobar su funcionamiento creando dos empleados validos para que notes que el cambio se guarda. 3. Este es mi código completo, modifícalo para enviar un Employee en lugar de Usuario: `import org.example.joseFrontend.model.User;` `import org.example.joseFrontend.repository.Repository;` `import org.example.joseFrontend.repository.UserRepository;` `import org.example.joseFrontend.util.DatabaseConnection;` `import java.sql.*;` `import java.util.List;` `public class Main {` ` public static void main(String[] args) throws SQLException {` ` try(Connection myConn = DatabaseConnection.``getInstance``()){` ` if(myConn.getAutoCommit()){` ` myConn.setAutoCommit(false);` ` }` ` User user1 = new User();` ` user1.setNickname("Architect");` ` user1.setPassword("admin123");` ` user1.setLogin("logead");` ` user1.setEmail("[email protected]");` ` user1.setNickname("DevOps");` ` User user2 = new User();` ` user2.setNickname("AWS");` ` user2.setPassword("admin123");` ` user2.setLogin("logead");` ` user2.setEmail("[email protected]");` ` user2.setNickname("DevOps");` ` List<User> usersList;` ` try{` ` Repository<User> userRepository = new UserRepository(myConn);` ` System.``out``.println("--------------Antes Cambio 1----------------");` ` usersList = userRepository.findAll();` ` usersList.forEach(System.``out``::println);` ` userRepository.save(user1);` ` System.``out``.println("--------------Después Cambio 1----------------");` ` usersList = userRepository.findAll();` ` usersList.forEach(System.``out``::println);` ` System.``out``.println("--------------Antes Cambio 2----------------");` ` userRepository.save(user2);` ` System.``out``.println("--------------Después Cambio 2----------------");` ` usersList = userRepository.findAll();` ` usersList.forEach(System.``out``::println);` ` System.``out``.println("-------------------------------------");` ` myConn.commit();` ` }catch (SQLException exception){` ` myConn.rollback();` ` }` ` }` ` }` `}`
La clase trata sobre la implementación de transacciones utilizando JDBC en Java. Se explica cómo gestionar transacciones en una base de datos, asegurando que múltiples operaciones se realicen de manera atómica. Se muestran ejemplos prácticos de cómo establecer y manejar conexiones, realizar commits y rollbacks, y cómo agregar nuevos campos a las tablas de la base de datos para mantener la integridad de los datos. Además, se discuten patrones de diseño como DAO y Repository para una gestión de datos más estructurada.
Para crear una columna llamada `curp` en una tabla existente en MySQL, puedes usar el siguiente código en MySQL Shell: ```sql ALTER TABLE Employees ADD COLUMN curp VARCHAR(18) UNIQUE; ``` Este código añade la columna `curp` de tipo `VARCHAR` con una longitud máxima de 18 caracteres y la establece como única, lo que significa que no puede haber valores duplicados en esta columna.
Configurando el autocommit en DatabaseConnection ```js public class DatabaseConnection { private static final String url = "jdbc:mysql://localhost:3306/project"; private static final String user = "admin"; private static final String pass = "admin123"; private static Connection connection; public static Connection getInstance() throws SQLException { if (connection == null) { connection = DriverManager.getConnection(url, user, pass); connection.setAutoCommit(false); } return connection; } } ```En Main ```js try(Connection connection = DatabaseConnection.getInstance()) { try { IRepository<Employee> employeeRepository = new EmployeeRepository(connection); System.out.println("--- Add new employee ---"); // Adding employee 1 Employee e = new Employee( "Carlangas", "Lanas Rosas", "1234567890" ); boolean done = employeeRepository.save(e); String msg = done ? "Employee created" : "Employee couldn't be created"; System.out.println("--- "+msg+" ---"); // Adding employee 2 Employee e2 = new Employee( "Papilla", "Rosales Candida", "1234567890" ); done = employeeRepository.save(e2); connection.commit(); msg = done ? "Employee created" : "Employee couldn't be created"; System.out.println("--- "+msg+" ---"); } catch (SQLException ex) { connection.rollback(); System.out.println("--- Rollback executed ---"); } } catch (SQLException e) { throw new RuntimeException(e); } ```Obtengo el siguiente resultado ```js --- Add new employee --- --- Employee created --- --- Rollback executed --- Process finished with exit code 0 ```
Hey, si no quieren borrar el paquete *view* y están usando un entorno como **Maven** o **Gradle** les recomiendo agregar lo siguiente. # Maven Dentro del **pom.xml** agreguen: ``` 1. \<project> 2. ... 3. \<build> 4. \<pluginManagement> 5. \<plugins> 6. \<plugin> 7. \<groupId>org.apache.maven.plugins\</groupId> 8. \<artifactId>maven-compiler-plugin\</artifactId> 9. \<version>3.11.0\</version> 10. \<configuration> 11. \<exclude> 12. \<exclude> 13. \*\*/view/SwingApp.java 14. \</exclude> 15. \</excludes> 16. \</configuration> 17. \</plugin> 18. \</plugins> 19. \</pluginManagement> 20. \</build> 21. ... 22. \</project> ``` # Gradle Dentro del **build.gradle** agreguen: ``` // código sourceSets { main { java { exclude '\*\*/view/SwingApp.java' } } } // más codigo ```
Para notar el funcinoamiento del rollback podemos realizar 02 consultas de tipo insert (metodo save() ). `public class ``Main {` ` ``public static void ``main(String[] args) ``throws ``SQLException {` ` ``//We create a new employee, we will use it later.` ` Employee employee03 = ``new ``Employee();` ` employee03.setFirst_name("luz");` ` employee03.setPa_surname("clarita");` ` employee03.setMa_surname("gutarra");` ` employee03.setEmail("[email protected]");` ` employee03.setSalary("50000");` ` employee03.setCurp("ROSAS1234567891R15");` ` Employee employee04 = ``new ``Employee();` ` employee04.setFirst_name("cielo");` ` employee04.setPa_surname("rosales");` ` employee04.setMa_surname("contreras");` ` employee04.setEmail("[email protected]");` ` employee04.setSalary("10000");` ` employee04.setCurp("ROSAS1234567891R15");` ` ``try``(Connection myConn = DataBaseConnection.getInstance()){` ` ``if``(myConn.getAutoCommit()){` ` myConn.setAutoCommit(``false``);` ` }` ` ``try``{` ` ``//We create an instance of EmployeeRepository` ` ``Repository<Employee> employeeRepository = ``new ``EmployeeRepository(myConn);` ` ``//Find all employees and then show them on the console.` ` ``employeeRepository.findAll().forEach(System.out::println);` ` System.out.println("*********************************************");` ` ``//We do two operations for modify data of the table` ` //insert (1)` ` ``employeeRepository.save(employee03);` ` ``//Find all employees and We see the change.` ` ``employeeRepository.findAll().forEach(System.out::println);` ` System.out.println("*********************************************");` ` ``//insert (2)` ` ``employeeRepository.save(employee04);` ` ``//Find all employees and We see the change.` ` ``employeeRepository.findAll().forEach(System.out::println);` ` } ``catch ``(SQLException e){` ` myConn.rollback();` ` ``throw new ``RuntimeException();` ` }` ` }` ` }` `}` El resultado que obtendremos sera el siguiente: ![](https://static.platzi.com/media/user_upload/rollback-355d8904-6f6a-4c4e-9fdc-54cf27f1c816.jpg) Aqui podemos ver que el primer listado es antes de realizar el insert, al segunda lista es despues de realizar el primer insert y vemos que si se anadio el registro. Al intentar realizar el segundo insert presenta un error por la duplicidad del 'corp', por lo que entra al catch( ) donde se ejecutar el 'rollback( )'. Si hacemos un SELECT desde nuestra BD o si volvemos a ejecutar el metodo findAll( ) desde el proyecto, veremos que ese registro que se inserto ya fue quitado. ![]()![](https://static.platzi.com/media/user_upload/rollback_1-e1de41fd-610e-4869-ad1c-3c90c808d4f5.jpg)
try(Connection myConn= CONECTARBD.*getInstance*()){ if(myConn.getAutoCommit()){ myConn.setAutoCommit(false); } try{ Repositorio\<PERSONA> repositorio =new CNPersona(myConn); System.*out*.println("----------- Ingreso de una nueva persona----------"); PERSONA persona=new PERSONA(); persona.setNombrePersona("Luis"); persona.setCedulaPersona("0103304531"); repositorio.Almacenar(persona); myConn.commit(); System.*out*.println("-------- IMPRIMIR TODOS LOS REGISTROS"); repositorio.LeerTodos().forEach(System.*out*::println); } catch (SQLException ex) { myConn.rollback(); throw new RuntimeException(ex); } } catch (SQLException ex) { throw new RuntimeException(ex); }
En mi caso: `public static void main(String[] args) throws SQLException { ` ` try(Connection conn= DataBaseConnection.getInstance()){` ` if(conn.getAutoCommit()){` ` conn.setAutoCommit(false);` ` }` ` try{` ` Repository<Employee> repository = new Employee_repository(conn);` ` System.out.println("....Insertar un nuevo cliente......");` ` Employee employee = new Employee();` `// employee.setFirts_name("Alejandra");` `// employee.setPa_surname("Ferrera");` `// employee.setMa_surname("Cáceres");` `// employee.setEmail("[email protected]");` `// employee.setSalary(3500F);` `// employee.setCurp("ALEJ123456741258EC");` `// repository.save(employee);` `// conn.commit();` ` ` ` employee.setFirts_name("Marco");` ` employee.setPa_surname("Nuñez");` ` employee.setMa_surname("Soto");` ` employee.setEmail("[email protected]");` ` employee.setSalary(3600F);` ` employee.setCurp("ALEJ123456741258EC");` ` repository.save(employee);` ` conn.commit();` ` }` ` catch(SQLException e){` ` conn.rollback();` ` throw new RuntimeException();` ` }`

Básicamente si creo mas empleados, como podria crear mas, deberia cambiar ese Curl? o ?

La operación la gestiono el manejador de Base de Datos porque al campo curp lo puso como UQ, no Java con el código.