Está en la página 1de 7

Introduccin 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.

Estableciendo una Conexin


La primera cosa para hacer, por su puesto, es instalar Java, JDBC y el DBMS en sus mquinas de trabajo. Desde que queremos interactuar con una base de datos Oracle, nosotros necesitaramos tambin un driver para esta base de datos especfica. Afortunadamente, nosotros tenemos un administrador responsable que ya ha hecho todos esto para nosotros en las mquinas de la Escuela.

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.

Creando una Instruccin JDBC


Un objeto Statement JDBC se usa para enviar sus declaraciones del SQL al DBMS, y no debe ser confundida con una declaracin SQL. Un objeto Statement JDBC es asociado con una conexin abierta, y no cualquier sola Declaracin del SQL. Usted puede pensar en un JDBC Declaracin objeto como un cauce que se sienta en una conexin, y pasando uno o ms de sus declaraciones del SQL (qu usted le pide que ejecute) al DBMS. Se necesita una conexin activa para crear un objeto Statement. El siguiente trozo de cdigo, usando nuestro objeto Connection con, lo hace: Statement stmt = con.createStatement() ; En este momento, existe un objeto Statement, pero no tiene una instruccin SQL para pasar al DBMS. Nosotros aprenderemos como hacerlo en la seccin siguiente.

Creando un Objeto PreparedStatement JDBC


Algunas veces, es ms conveniente o ms eficiente usar un objeto PreparedStatement para enviar las instrucciones SQL al DBMS. La caracterstica principal que lo distingue de su superclase Statement, es que a diferencia de la instruccin Statement, ella est dando una instruccin SQL correcta cuando se crea. Esta instruccin SQL se enva en seguida al DBMS, dnde es compilada. Entonces, en efecto, un objeto PreparedStatement es asociado como un canal con una conexin y una instruccin SQL compilada. La ventaja ofrecida es que si necesita usar la misma, o similar consulta con diferentes parmetros varias veces, la

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");

Ejecutando una Instruccin CREATE/INSERT/UPDATE


La Ejecucin de las instrucciones SQL en JDBC vara dependiendo de la la intencin de la instruccin SQL. Las instrucciones DDL (data definition language) tales como la creacin de una tabla y la alteracin de una tabla, as como las declaraciones para actualizar el contenido de una tabla, son todas ejecutadas usando el mtodo executeUpdate. Note que estos comandos cambian el estado de la base de datos, ya que el nombre del mtodo contiene Update. Veamos los siguientes ejemplos de instrucciones executeUpdate: Statement stmt = con.createStatement(); stmt.executeUpdate("CREATE TABLE Venta " + "( nombreBar VARCHAR2(40), marcaCerveza VARCHAR2(40), precio REAL)" ); stmt.executeUpdate("INSERT INTO Venta " + "VALUES ('El Cantinazo', 'Riverea', 1000)" ); String sqlString = "CREATE TABLE Bares " + "( nombreBar VARCHAR2(40), direccion VARCHAR2(80), licencia INT)" ; stmt.executeUpdate(sqlString); Ya que la instruccin SQL no encajar en una lnea en la pgina, hemos dividido en dos cadenas concatenadas por un signo ms (+) para que compilara. Preste atencin a la instruccin "INSERT INTO Venta", se ha separado en la cadena de la clusula VALUES". Note que estamos reusando el mismo objeto Statement en lugar de haber creado un nuevo objeto. Cuando se usa executeUpdate para llamar las instrucciones DDL, el valor devuelto es siempre cero, mientras la ejecucin de instrucciones de modificacin de datos devolvern un valor mayor que cero, el cual es el nmero de tuplas afectadas en la relacin. Mientras esta trabajando con un PreparedStatement, debemos ejecutar tal consulta por el primer plugging en los valores de los parmetros (como vimos anteriormente), y luego invocando el executeUpdate sobre l.
int n = prepareUpdatePrecio.executeUpdate();

Ejecutando una Instruccin SELECT


En oposicin a las instrucciones anteriores, se espera que una consulta devuelva un conjunto de tuplas como resultado, y no cambia el estado de la base de datos. No es sorprendentemente, ya que un mtodo correspondiente llamado executeQuery, devuelve sus resultados como un objeto de ResultSet: String nombreBar, marcaCerveza ; float precio ;
ResultSet rs = stmt.executeQuery("SELECT * FROM Venta"); while ( rs.next() ) { nombreBar = rs.getString("nombreBar"); marcaCerveza = rs.getString("marcaCerveza"); precio = rs.getFloat("precio"); System.out.println(nombreBar+" vende "+marcaCerveza+" a "+precio+" Pesos."); }

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() ;

Notas Sobre Accessos ResultSet


JDBC tambin le ofrece varios mtodos para averiguar dnde est ubicado en el conjunto resultante usando getRow, isFirst, isBeforeFirst, isLast, isAfterLast. Hay la forma de hacer los cursores desplegables para permitir libre acceso a cualquier fila en el conjunto resultante. Por defecto, los cursores desplazan hacia adelante solamente y slo son de lectura. Cuando se crea una Statement para una Connection, se puede cambiar el tipo de ResultSet a un modelo desplegable ms flexible o actualizable: Statement stmt = con.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stmt.executeQuery("SELECT * FROM Venta"); Las diferentes opciones para los tipos son TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE y TYPE_SCROLL_SENSITIVE. Usted puede escoger si el cursor es de slo lectura o actualizable usando las

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.

Manejo de Errores con Exceptions


La verdad es que siempre ocurren errores en los programas de software. A menudo, los programas de base de datos son aplicaciones crticas, y es indispensable que los errores se capturen y se manejen limpiamente. Los Programas deben recuperar y dejar la base de datos en un estado consistente. El rollback usado junto con el manejo de excepciones de Java es una forma decorosa de lograr tal requisito. El programa (cliente) accediendo una base de datos (servidor) necesita ser consciente de cualquier error devuelto por el servidor. JDBC da acceso a la tal informacin proporcionando dos niveles de condiciones del error: SQLException y SQLWarning. SQLExceptions son las excepciones de Java que, si no manej, terminarn la aplicacin. SQLWarnings son subclasses de SQLException, pero ellas representan errores no fatales o condiciones inesperadas, las cuales puede ignorarse. En Java, declaraciones de las cuales se espera disparen una excepcin o una advertencia son encerradas en un bloque try. Si una declaracin en bloque try dispara una excepcin o una advertencia, puede ser capturada en una de las declaraciones de captura (catch) correspondientes. Cada declaracin catch especifica cual excepciones esta disponible para capturar. Aqu es un ejemplo de captura de un SQLException, y usando la condicin de error para reversar la transaccin: try { con.setAutoCommit(false) ; stmt.executeUpdate("CREATE TABLE Venta (nombreBar VARCHAR2(40)," + " marcaCerveza VARHAR2(40), precio REAL)") ; stmt.executeUpdate("INSERT INTO Venta VALUES " + "('Bar Ato', 'Mellir', 1200)") ; con.commit() ; con.setAutoCommit(true) ; }catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage()) ; con.rollback() ; con.setAutoCommit(true) ; }

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.

También podría gustarte