Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Introduccion Al JDBC
Introduccion Al JDBC
Este documento ilustra los elementos esenciales del JDBC (Java Database Connectivity) API (Application Program Interface). Aqu, usted aprender a usar el API de JDBC bsico para crear las tablas, insertar valores, consultar tablas, recuperar resultados, actualizar tablas, crear declaraciones preparadas, realizar transacciones y capturar excepciones y errores. Este documento se obtiene de la gua didctica oficial de JDBC, de Sun, JDBC Basics: http://java.sun.com/docs/books/tutorial/jdbc/basics/index.html
Resumen General Estableciendo una Conexin Creando una Instruccin JDBC Creando un Objeto PreparedStatement JDBC Ejecutando instrucciones CREATE/INSERT/UPDATE Ejecutando una Instruccin SELECT Notas Sobre Accesos ResultSet Transacciones Manejando Errores con Excepciones
Resumen general
Las interfaces a nivel de llamado como JDBC son interfaces de programacin que permiten el acceso externo a comandos de manipulacin y actualizacin SQL de la base de datos. Ellos permiten la integracin de llamadas del SQL en un entorno de programacin general proporcionando una biblioteca de rutinas las cuales interactan con la base de datos. En particular, Java basado en JDBC tiene una rica coleccin de rutinas que hacen tal interfaz sumamente simple e intuitiva. Aqu hay una manera fcil de visualizar lo que pasa en una interfaz de nivel de llamada: Usted est escribiendo un programa de Java normal. En alguna parte en el programa, usted necesita actuar recprocamente con una base de datos. Usando las rutinas de la biblioteca estndar, usted abre una conexin a la base de datos. Usted entonces usa JDBC entonces para enviar su cdigo del SQL a la base de datos, y procesa los resultados que se devuelven. Cuando usted ha terminado, cierra la conexin. Tal enfoque tiene que ser contrastado con la ruta de precompilacin tomada con el SQL Embebido. El ltimo tiene un paso de precompilacin dnde el cdigo del SQL embebido se convierte al cdigo del lenguaje husped (C/C++). Las interfaces a nivel de llamado no requieren la precompilacin y as evitan algunos de los problemas de SQL embebido. El resultado es aumentar la portabilidad y una relacin cliente-servidor ms limpia.
Como dijimos inicialmente, antes de acceder a una base de datos, debe abrirse una conexin entre nuestro programa (cliente) y la base de datos (servidor). Esto involucra dos pasos:
Cargue el driver especfico Por qu necesitamos este paso? Para asegurar portabilidad y reutilizacin del cdigo, el API fue diseado para ser independiente de la versin o el vendedor de una base de datos. Ya que diferentes DBMS tiene funcionamiento diferente, necesitamos decirle al driver administrador del DBMS que deseamos usarlo, para que pueda invocar el driver correcto. Un driver de Oracle es cargado usando el siguiente trozo de cdigo: Class.forName("oracle.jdbc.driver.OracleDriver")
Hacer una conexion Una vez el driver es cargado y listo para realizar una conexin, usted puede crear una instancia de un objeto Connection usando: Connection con = DriverManager.getConnection( jdbc:oracle:thin:@192.168.131.93:1521:ictus, scott, tigger); Veamos lo que significa esta jerga. El primer string es la direccin URL para la base de datos incluyendo el protocolo (JDBC), el vendedor (Oracle), el driver (thin), el nmero del puerto (1521), y el servidor (ictus). El nombre de usuario y la contrasea son scott y tigger, el mismo con que ingresa a SQLPLUS para acceder su cuenta.
La conexin retornada en el ltimo paso es una conexin abierta que usaremos para pasar las declaraciones SQL a la base de datos. En este trozo del cdigo, con es una conexin abierta, y nosotros la usaremos abajo.
instruccin puede ser compilada y optimizada por el DBMS slo una vez. Contrasta esto con un uso de una Statement normal dnde cada uso de la misma instruccin SQL requiere una compilacin de nuevo. Tambin se crean PreparedStatements con un mtodo Connection. El siguiente trozo muestra cmo crear una instruccin SQL parametrizada con tres parmetros de entrada: PreparedStatement prepareUpdatePrice = con.prepareStatement( "UPDATE Venta SET precio = ? WHERE nombreBar = ? AND marcaCerveza = ?"); Antes de que podamos ejecutar un PreparedStatement, necesitamos proporcionar los valores de los parmetros. Esto puede hacerse llamando uno de los mtodos del setXXX definido en la clase PreparedStatement. Los mtodos ms usados son los setInt, setFloat, setDouble, setString, etc. Usted puede poner estos valores antes de cada ejecucin de la instruccin preparada. Continuando el ejemplo anterior, escribiremos: prepareUpdatePrecio.setInt(1, 1000); prepareUpdatePrecio.setString(2, "El Cantinazo"); prepareUpdatePrecio.setString(3, "Riverea");
La bolsa de tuplas resultante de la consulta est contenida en la variable rs, la cual es una instancia de ResultSet. Un conjunto no es de mucha utilidad a menos que podemos acceder cada fila y los atributos en cada fila. El ResultSet nos proporciona un cursor, que podemos usar para acceder cada fila a la vez. El cursor es inicialmente fijado antes de la primera fila. Cada invocacin del mtodo next causa que el cursor se mueva a la siguiente fila, si ella existe retorna verdadero (true), o retorno falso (false) si no hay fila de retorno. Podemos usar el mtodo del getXXX del tipo apropiado para recuperar los atributos de una fila. En el ejemplo anterior, nosotros usamos los mtodos getString y getFloat para acceder los valores de la columna. Observe que debemos proporcionar el nombre de la columna cuyo valor se desea adquirir, como parmetro al mtodo. Tambin debemos observar que los atributos de tipo VARCHAR2 nombreBar, marcaCerveza, se han convertido a un String de Java, y el REAL al tipo float de Java. Equivalentemente, podemos especificar el nmero de la columna en lugar del nombre de la columna, con el mismo resultado. As las declaraciones pertinentes seran: nombreBar = rs.getString(1); precio = rs.getFloat(3); marcaCerveza = rs.getString(2); Mientras se trabaja con un PreparedStatement, debemos ejecutar tal consulta por el primer plugging en los valores de los parmetros, e invocando luego el executeQuery sobre l. ResultSet rs = prepareUpdatePrice.executeQuery() ;
opciones CONCUR_READ_ONLY, y CONCUR_UPDATABLE. Con el cursor predefinido, usted puede desplazar usando rs.next(). Con los cursores desplegabless usted tiene ms opciones: rs.absolute(3); // se mueve a la tercera tupla rs.previous(); // se mueve hacia atrs una tupla (tupla 2) rs.relative(2); // se mueve hacia delante dos tuplas (tupla 4) rs.relative(-3); // se mueve hacia atrs tres tuplas (tuple 1) Hay una gran cantidad de detalles en el desempeo de un cursor desplegable. Los cursores desplegables, aunque bastante tiles para ciertas aplicaciones, son extremadamente susceptibles de traspasar los lmites (overhead), y deben usarse en forma restringida y con cautela. Ms informacin puede encontrarse en http://java.sun.com/docs/books/tutorial/jdbc/jdbc2dot0/index.html dnde puede hallar una gua didctica ms detallada acerca de las tcnicas de manipulacin del cursor.
Transacciones
JDBC permite agrupar instrucciones SQL en una sola transaccin. As, podemos asegurar las propiedades ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad) usando las facilidades transaccionales del JDBC. El control de la transaccin es realizado por el objeto Connection. Cuando una conexin se crea, por defecto es en modo auto - commit. Esto significa que cada instruccin individual SQL se trata como una transaccin en s misma, y se comprometer en cuanto la ejecucin sea terminada. (Esto no es exactamente preciso, pero podemos encubrir esta sutileza por propsitos didcticos). Nosotros podemos desactivar el modo auto - commit para una conexin activa con: con.setAutoCommit(false) ; y se lo vuelve a activar con: con.setAutoCommit(true) ; Una vez que el auto-commit is desactivado, ninguna declaracin del SQL se comprometer (es decir, la base de datos no se actualizar permanentemente) hasta que usted le haya dicho explcitamente que comprometa invocando el mtodo commit(): con.commit() ; A cualquier punto antes del commit, podemos invocar un rollback () para reversar la transaccin, y restaurar los valores al ltimo punto de commit (antes de las actualizaciones intentadas). Aqu hay un ejemplo que presenta estas ideas: con.setAutoCommit(false); Statement stmt = con.createStatement(); stmt.executeUpdate("INSERT INTO Venta VALUES('El Cantinazo','Riverea',1000)" ); con.rollback(); stmt.executeUpdate("INSERT INTO Sells VALUES('Bar Ato', 'Mellir', 1200)" ); con.commit(); con.setAutoCommit(true); Examinemos el ejemplo para entender los efectos de varios de los mtodos. Primero se declar desactivar el autocommit, indicando eso que las siguientes instrucciones necesitaban considerarse como una unidad. Luego intentamos insertar en la tabla Venta la tupla ('El Cantinazo','Riverea',1000). Sin embargo, este cambio no ser realizado hasta el final (cuando se ejecute el commit). Cuando invocamos el rollback, nosotros cancelamos la anterior insercin y en efecto se elimina cualquier intencin de insertar la tupla anterior. Note que Venta ahora todava es como era antes de que intentramos la insercin. Ahora intentamos otra insercin, y esta vez, nosotros comprometemos la transaccin. Slo es ahora que Venta se afecta permanentemente y tiene una
nueva tupla en ella. Finalmente, restablecemos la conexin para realizar de nuevo un auto-commit. Tambin podemos asignar niveles de aislamiento de la transaccin como se desee. Por ejemplo, podemos asignar el nivel de aislamiento de transaccin en TRANSACTION_READ_COMMITTED, que no permitir acceder un valor hasta despus de que haya sido comprometido (committed), y puede prohibir las lecturas sucias. Hay cinco que valores para niveles de aislamiento proporcionados en la interfaz Connection. Por defecto, el nivel de aislamiento es el serializable. JDBC nos permite definir el nivel de aislamiento de transaccin a la base de datos (usando el mtodo de Connection : getTransactionIsolation ) y asignar el nivel apropiado (usando el mtodo de Connection : setTransactionIsolation). Normalmente se usar rollback en combinacin con el manejo de excepciones de Java para recuperar errores predecibles (o no). Tal una combinacin provee un mecanismo excelente y fcil para el manejo de integridad de los datos. Estudiamos el tratamiento de errores que usa JDBC en la siguiente seccin.
En este caso, se dispara una excepcin porque marcaCerveza est definida como VARHAR2 que es un error de sintaxis. No hay tal tipo de datos en nuestro DBMS, entonces se dispara un SQLException. La salida en este caso ser: Message: ORA-00902: invalid datatype
Alternativamente, si los tipos de dato estn correctos, una excepcin podra dispararse en caso de que el tamao de la base de datos exceda la cuota de espacio y sea incapaz de construir una nueva tabla. Un SQLWarning puede ser regresado de los objetos Connection, Statement y ResultSet. Cada uno slo almacena el ms reciente SQLWarning. As si usted ejecuta otra declaracin a travs de su objeto Statement, cualquier advertencia ms temprana ser descartada. Aqu hay un trozo de cdigo que ilustra el uso de SQLWarning: ResultSet rs = stmt.executeQuery("SELECT nombreBar FROM Venta") ; SQLWarning warn = stmt.getWarnings() ; if (warn != null) System.out.println("Message: " + warn.getMessage()) ; SQLWarning warning = rs.getWarnings() ; if (warning != null) warning = warning.getNextWarning() ; if (warning != null) System.out.println("Message: " + warn.getMessage()) ; Los SQLWarnings (en oposicin a SQLExceptions) son realmente raros -- el ms comn es una advertencia de DataTruncation. Este ltimo indica que hay un problema mientras esta leyendo o escribiendo datos de la base de datos.