Tema 2: JDBC PDF
Document Details
Uploaded by Deleted User
Tags
Summary
These are notes on JDBC. The document details basic concepts and examples of Java DataBase Connectivity (JDBC), including database access, configuration and the use of Java objects with databases. It covers topics like drivers, data types, and prepared statements.
Full Transcript
Tema 2: JDBC Índice Introducción Accesos básicos Tipos SQL y Java DataSources Pool de conexiones Transacciones Otros temas Tema 2 - 2 Introducción (1) Objetivos de este apartado Entender...
Tema 2: JDBC Índice Introducción Accesos básicos Tipos SQL y Java DataSources Pool de conexiones Transacciones Otros temas Tema 2 - 2 Introducción (1) Objetivos de este apartado Entender los mecanismos básicos de la API Java estándar de acceso a BBDD relacionales Aprender aspectos básicos de configuración de acceso a una BD desde un servidor de aplicaciones Java (e.g. Jetty, Tomcat, etc.) Tema 2 - 3 Introducción (y 2) JDBC (Java DataBase Connectivity) es una API estándar que permite lanzar consultas a una BD relacional El desarrollador siempre trabaja contra los paquetes java.sql y javax.sql Forman parte de Java SE Contienen un buen número de interfaces y algunas clases concretas, que conforman la API de JDBC Para poder conectarse a la BD y lanzar consultas, es preciso tener un driver adecuado para ella Un driver suele ser un fichero.jar que contiene una implementación de todas las interfaces de la API de JDBC El driver lo proporciona el fabricante de la BD o un tercero Nuestro código nunca depende del driver, dado que siempre trabaja contra los paquetes java.sql y javax.sql Tema 2 - 4 Driver JDBC Aplicación java.sql javax.sql Driver JDBC BD Tema 2 - 5 Independencia de la BD Idealmente, si nuestra aplicación cambia de BD, no necesitamos cambiar el código; simplemente, necesitamos otro driver Sin embargo, desafortunadamente las BBDD relacionales usan distintos dialectos de SQL (¡a pesar de que en teoría es un estándar!) Tipos de datos: varían mucho según la BD Generación de identificadores: secuencias, autonumerados, etc. Cuando se desea que el código sea independiente de la BD, es posible utilizar técnicas (patrones) para hacer frente a este problema Tema 2 - 6 Ejemplos Los siguientes ejemplos ilustran el uso de la API básica de JDBC Hacen uso de la tabla TutMovie (PK) movieId title runtime (VARCHAR) (VARCHAR) (SMALLINT) Tema 2 - 7 Ejemplo de actualización: es.udc.ws.jdbctutorial.InsertExample (1) package es.udc.ws.jdbctutorial; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public final class InsertExample { public static void main (String[] args) { try (Connection connection = ConnectionManager.getConnection()) { String[] movieIdentifiers = new String[] {"movie-1", "movie-2”, "movie-3"}; String[] titles = new String[] {"movie-1 title", "movie-2 title”, "movie-3 title"}; short[] runtimes = new short[] {90, 120, 150}; String queryString = "INSERT INTO TutMovie " + "(movieId, title, runtime) VALUES (?, ?, ?)"; PreparedStatement preparedStatement = connection.prepareStatement(queryString); Tema 2 - 8 Ejemplo de actualización: es.udc.ws.jdbctutorial.InsertExample (y 2) for (int i=0; i } catch (Exception e) { e.printStackTrace(System.err); } finally { try { if (connection != null) { connection.close(); } } catch (Exception e) { e.printStackTrace(System.err); } } Tema 2 - 23 Liberación de recursos (4) finalize La implementación de la interfaz Connection debe redefinir finalize para que invoque a close en caso de que el desarrollador no lo haya hecho NOTA: finalize es un método definido en Object; el recolector de basura lo invoca antes de eliminar un objeto de memoria En resumen, se crea la ilusión de que podríamos interactuar con la BD de la siguiente manera, es decir, sin cerrar la conexión explícitamente ni implícitamente vía try- with-resources try { Connection connection = ConnectionManager.getConnection(); > } catch (Exception e) { e.printStackTrace(System.err); } Tema 2 - 24 Liberación de recursos (5) Sin embargo, en un caso real, no sería buena idea... Supongamos una aplicación servidora multi-thread, donde cada thread puede tener que acceder a la BD Un ejemplo de tal aplicación servidora es un servicio/aplicación Web Java Como veremos más adelante, los servicios/aplicaciones Web Java se ejecutan normalmente dentro de servidores de aplicaciones Un servidor de aplicaciones atiende cada petición HTTP en un thread Es posible atender múltiples peticiones concurrentemente Navegador … … Navegador BD Servidor de aplicaciones Tema 2 - 25 Liberación de recursos (6) Sin embargo, en un caso real, no sería buena idea… (cont) Además, un gestor de BD no puede tener abiertas más de un determinado número “n” de conexiones Si cada thread que accede a la BD, no cierra la conexión una vez termine su trabajo, la conexión no se cerrará hasta que el recolector de basura elimine esa conexión (que se ha quedado sin referenciar) En un momento dado, puede ocurrir que se hayan procesado “n” peticiones HTTP y que sus respectivas conexiones todavía no hayan sido eliminadas por el recolector de basura NOTA: el recolector de basura decide eliminar memoria cuando lo considera oportuno (e.g. cuando se lleva consumido cierta cantidad de memoria) Cuando llegue la siguiente petición, DriverManager.getConnection devolverá SQLException porque la BD no admite más conexiones Las “n” conexiones anteriores todavía no se han liberado, a pesar de que nadie las está usando Tema 2 - 26 Liberación de recursos (y 7) Conclusión Cada thread debe liberar la conexión inmediatamente una vez termine de interactuar con la BD, bien explícitamente, o bien mediante try-with-resources Tema 2 - 27 Tipos SQL y Java ResultSet y PreparedStatement proporcionan métodos getXXX y setXXX ¿Cuál es la correspondencia entre tipos Java y tipos SQL? Idea básica: un dato de tipo Java se puede almacenar en una columna cuyo tipo SQL sea consistente con el tipo Java Tema 2 - 28 Correspondencia entre tipos Java y SQL estándar Tipo Java Tipo SQL boolean BIT byte TINYINT short SMALLINT int INTEGER long BIGINT float REAL double DOUBLE java.math.BigDecimal NUMERIC String VARCHAR o LONGVARCHAR byte[] VARBINARY o LONGVARBINARY java.sql.Date DATE java.sql.Time TIME java.sql.Timestamp TIMESTAMP Tema 2 - 29 DataSources Interfaz javax.sql.DataSource Entre otros, dispone del método getConnection DataSource dataSource =... Connection connection = dataSource.getConnection(); Cuando se utiliza esta interfaz, el desarrollador no tiene que especificar la URL, el usuario y la contraseña para pedir la conexión Los servidores de aplicaciones Java y algunos frameworks ofrecen implementaciones de la interfaz DataSource A nivel de implementación utilizan DriverManager.getConnection para obtener las conexiones, aunque como veremos más adelante, la estrategia puede ser compleja Utilizan ficheros de configuración para especificar, como mínimo, la URL, el usuario y la contraseña Tanto con Jetty como con Tomcat (servidores de aplicaciones) configuraremos objetos DataSource para acceder a la BD Tema 2 - 30 Pool de conexiones (1) Problema Servidor de aplicaciones que recibe muchas peticiones HTTP por minuto Es posible pedir una conexión a la BD con DriverManager.getConnection o el método getConnection de un objeto DataSource DriverManager.getConnection pide una conexión directamente a la BD Es una operación lenta => se convierte en cuello de botella En una implementación básica de DataSource, el método getConnection también invoca DriverManager.getConnection Además, con cualquiera de los dos métodos, si en ese momento la BD ya no admite más conexiones (porque se supera el máximo permitido), los métodos getConnection devuelven una excepción Tema 2 - 31 Pool de conexiones (2) Solución: pool de conexiones Los servidores de aplicaciones Java proporcionan implementaciones de DataSource que utilizan la estrategia pool de conexiones El objeto DataSource gestiona un conjunto de conexiones que previamente ha solicitado a la BD El desarrollador sólo trabaja contra la interfaz DataSource La estrategia es transparente al desarrollador Tema 2 - 32 Pool de conexiones (3) Pide “n” conexiones a la BD inicialmente Navegador … … ConnectionPool BD Navegador Servidor de aplicaciones java.sql.Connection javax.sql.DataSource ConnectionPool ConnectionProxy - connections: java.util.List - c : java.sql.Connection releaseConnection(c:Connection):void Tema 2 - 33 Pool de conexiones (4) ConnectionPool Cuando se crea, pide “n” conexiones a la BD (usando DriverManager.getConnection) y las almacena en una lista getConnection Si quedan conexiones libres en la lista, elige una, la marca como usada, y devuelve un objeto ConnectionProxy que la contiene En otro caso, deja durmiendo (wait) al thread llamador releaseConnection Devuelve la conexión a la lista, la marca como libre, y notifica (notifyAll) a los posibles threads que esperan por una conexión ConnectionProxy Proxy de la conexión real close Usa releaseConnection para devolver la conexión real al pool finalize Si no se ha llamado a ConnectionProxy.close, lo llama Resto de operaciones Delegan en la conexión real Tema 2 - 34 Pool de conexiones (5) Observaciones Cuando el desarrollador invoca getConnection sobre el objeto DataSource Si hay una conexión libre => se le devuelve rápidamente de la lista (no se accede a BD) Si no hay ninguna conexión libre => el thread llamador se queda dormido hasta que haya una Las conexiones reales no se cierran (se devuelven al pool) Tema 2 - 35 Pool de conexiones (y 6) Caídas de la BD Si la BD se cae, las conexiones del pool se invalidan aunque se vuelva a rearrancar la BD (porque los sockets subyacentes ya no son válidos) Para hacer frente a este problema, la implementación de getConnection puede comprobar si la conexión que devuelve es correcta (está viva) Opción 1: haciendo uso de una API específica del fabricante del driver Opción 2: lanzando una consulta poco costosa a la BD (si no se produce una SQLException, la conexión es correcta) Configuración del pool Además de la configuración básica de un DataSource, se puede especificar el número de conexiones a la BD que se solicitan inicialmente, la consulta de comprobación de conexión viva (si se requiere), etc. Tema 2 - 36 Transacciones Permiten ejecutar bloques de código con las propiedades ACID (Atomicity-Consistency-Isolation- Durability) Por defecto, cuando se crea una conexión está en modo auto-commit Cada consulta lanzada se ejecuta en su propia transacción Para ejecutar varias consultas en una misma transacción es preciso Deshabilitar el modo auto-commit de la conexión Lanzar las consultas Terminar con connection.commit() si todo va bien, o connection.rollback() en otro caso. Tema 2 - 37 es.udc.ws.jdbctutorial.TransactionExample (1) Mismo ejemplo que es.udc.ws.jdbctutorial.InsertExample, pero ahora la inserción de películas se realiza en una única transacción public final class TransactionExample { public static void main (String[] args) { try (Connection connection = ConnectionManager.getConnection()) { try { connection.setAutoCommit(false); > connection.commit(); System.out.println("Movies inserted"); Tema 2 - 38 es.udc.ws.jdbctutorial.TransactionExample (y 2) } catch (Exception e) { connection.rollback(); throw e; } } catch (Exception e) { e.printStackTrace(System.err); } } } Tema 2 - 39 Transaction isolation levels (1) java.sql.Connection proporciona el método setTransactionIsolation, que permite especificar el nivel de aislamiento deseado TRANSACTION_NONE: transacciones no soportadas TRANSACTION_READ_UNCOMMITTED: pueden ocurrir “dirty reads”, “non-repeatable reads” y “phantom reads” TRANSACTION_READ_COMMITTED: pueden ocurrir “non- repeatable reads” y “phantom reads” TRANSACTION_REPEATABLE_READ: pueden ocurrir “phantom reads” TRANSACTION_SERIALIZABLE: elimina todos los problemas de concurrencia Mayor nivel de aislamiento => la BD realiza más bloqueos => menos concurrencia Tema 2 - 40 Transaction isolation levels (y 2) Por sencillez, en la asignatura realizaremos las transacciones con el nivel de aislamiento TRANSACTION_SERIALIZABLE Existen técnicas que permiten trabajar transaccionalmente en muchas situaciones con un nivel de aislamiento inferior Menos bloqueos en la BD En “Programación Avanzada” se estudia la técnica de “Optimistic Locking” Tema 2 - 41