La forma de permitir que dos o más sentencia sean agrupadas en una transación es desactivar el modo auto-entrega. Esto se demuestra en el siguiente código, donde con es una conexión activa:
con.setAutoCommit(false);
con.setAutoCommit(false); PreparedStatement updateSales = con.prepareStatement( "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?"); updateSales.setInt(1, 50); updateSales.setString(2, "Colombian"); updateSales.executeUpdate(); PreparedStatement updateTotal = con.prepareStatement( "UPDATE COFFEES SET TOTAL = TOTAL + ? WHERE COF_NAME LIKE ?"); updateTotal.setInt(1, 50); updateTotal.setString(2, "Colombian"); updateTotal.executeUpdate(); con.commit(); con.setAutoCommit(true);En este ejemplo, el modo auto-entrega se desactiva para la conexión con, lo que significa que las dos sentencias prepared updateSales y updateTotal serán entregadas juntas cuando se llame al método commit. Siempre que se llame al método commit (bien automáticamente, cuando está activado el modo auto-commit o explícitamente cuando está desactivado), todos los cambios resultantes de las sentencias de la transación serán permanentes. En este caso, significa que las columnas SALES y TOTAL para el café Colombian han sido cambiadas a 50 (si TOTAL ha sido 0 anteriormente) y mantendrá este valor hasta que se cambie con otra sentencia de actualización.
La línea final del ejemplo anterior activa el modo auto-commit, lo que significa que cada sentencia será de nuevo entregada automáticamente cuando esté completa. Volvemos por lo tanto al estado por defecto, en el que no tenemos que llamar al método commit. Es bueno desactivar el modo auto-commit sólo mientras queramos estar en modo transación. De esta forma, evitamos bloquear la base de datos durante varias sentencias, lo que incrementa los conflictos con otros usuarios.
Esta clase de situaciones puede evitarse utilizando Transaciones. Si un controlador de base de datos soporta transaciones, y casi todos lo hacen, proporcionará algún nivel de protección contra conflictos que pueden surgir cuando dos usuarios acceden a los datos a la misma vez.
Para evitar conflictos durante una transación, un controlador de base de datos utiliza bloqueos, mecanismos para bloquear el acceso de otros a los datos que están siendo accedidos por una transación. (Observa que en el modo auto-commit, donde cada sentencia es una transación, el bloqueo sólo se mantiene durante una sentencia). Una vez activado, el bloqueo permanece hasta que la transación sea entregada o anulada. Por ejemplo, un controlador de base de datos podría bloquear una fila de una tabla hasta que la actualización se haya entregado. El efecto de este bloqueo es evitar que usuario obtenga una lectura sucia, esto es, que lea un valor antes de que sea permanente. (Acceder a un valor actualizado que no haya sido entregado se considera una lectura sucia porque es posible que el valor sea devuelto a su valor anterior. Si leemos un valor que luego es devuelto a su valor antiguo, habremos leído un valor nulo).
La forma en que se configuran los bloqueos está determinado por lo que se llama nivel de aislamiento de transación, que pude variar desde no soportar transaciones en absoluto a soportar todas las transaciones que fuerzan una reglas de acceso muy estrictas.
Un ejemplo de nivel de aislamiento de transación es TRANSACTION_READ_COMMITTED, que no permite que se acceda a un valor hasta que haya sido entregado. En otras palabras, si nivel de aislamiento de transación se selecciona a TRANSACTION_READ_COMMITTED, el controlador de la base de datos no permitirá que ocurran lecturas sucias. El interface Connection incluye cinco valores que representan los niveles de aislamiento de transación que se pueden utilizar en JDBC.
Normalmente, no se necesita cambiar el nivel de aislamiento de transación; podemos utilizar el valor por defecto de nuestro controlador. JDBC permite averiguar el nivel de aislamiento de transación de nuestro controlador de la base de datos (utilizando el método getTransactionIsolation de Connection) y permite configurarlo a otro nivel (utilizando el método setTransactionIsolation de Connection). Sin embargo, ten en cuenta, que aunque JDBC permite seleccionar un nivel de aislamiento, hacer esto no tendrá ningún efecto a no ser que el driver del controlador de la base de datos lo soporte.