Sie sind auf Seite 1von 11

Prctica Base de datos BASES DE DATOS y JDBC 1.

Creacin de una base de datos en MySQL Iniciar y utilizar el servidor MySQL Creacin de una Base de Datos y sus tablas por medio de un fichero script 2. Operaciones sobre la BD desde Java con JDBC Introduccin a JDBC Paquete java.sql Pasos para crear una aplicacin JDBC Cargar el driver JDBC Conectarse a una Base de Datos Consultar la Base de Datos Consultas de Actualizacin Sentencias de tipo PreparedStatement Utilizacin de Metadata Informacin de una Base de Datos Informacin de un ResultSet Clase que prueba el acceso a datos 1. Creacin de una base de datos en MySQL MySQL es un servidor de bases de datos multihilo y multiusuario, robusto y muy rpido. Permite la creacin de bases de datos relacionales que pueden ser consultadas a travs de SQL (Structure Query Language) estndar. Referencias: para instalacin: http://www.mysql.com. Iniciar y utilizar el servidor MySQL Instruccin para iniciarlo C:\> C:\mysql\bin\mysqld-max-nt --standalone Iniciarlo como un servicio (usualmente ya lo estar) C:\> C:\mysql\bin\mysqld-max-nt --install Para conectarse shell> mysql Para desconectarse mysql> QUIT Creacin de una Base de Datos y sus tablas por medio de un fichero script En MySQL se puede crear un fichero script que contenga todos los comandos que necesitamos ejecutar. Este fichero solo debe ser un fichero de texto que contenga las rdenes terminadas en punto y coma. A continuacin ponemos un ejemplo de un fichero BDCoches.txt que permite la

creacin de una bases de datos DatosCoches y dos tablas relacionadas Propietarios y Coches, donde Propietarios es la tabla principal de la relacin con DNI como clave principal y Coches es la tabla relacionada con Matrcula como clave principal: CREATE DATABASE DatosCoches; USE DatosCoches; CREATE TABLE PROPIETARIOS (DNI VARCHAR(10), Nombre VARCHAR(40), Edad INTEGER, PRIMARY KEY(DNI)); CREATE TABLE COCHES (Matricula VARCHAR(10) , Marca VARCHAR(20), Precio INTEGER, DNI VARCHAR (10), PRIMARY KEY(Matricula), FOREIGN KEY (DNI) References Propietarios); INSERT INTO Propietarios values('1A','Pepe',30); INSERT INTO Propietarios values('1B','Ana',40); INSERT INTO Propietarios values('1C','Maria',50); INSERT INTO Coches values('MA-1111','Opel',1000,'1A'); INSERT INTO Coches values('MA-2222','Renault',2000,'1A'); INSERT INTO Coches values('BA-3333', 'Seat', 3000,'1B'); Describe Propietarios; Describe Coches; Select * from Propietarios; Select * from Coches; Select * from Propietarios, Coches where Propietarios.DNI=Coches.DNI; El comando que se utiliza para poder ejecutar todas las rdenes que se encuentran en este fichero desde MySQL es: mysql> SOURCE BDCoches.txt Operaciones sobre la BD desde Java con JDBC Introduccin a JDBC JDBC es un API de Java para ejecutar sentencias SQL. Est formado por un conjunto de clases e interfaces programadas con el propio Java. Permite interactuar con bases de datos, de forma transparente al tipo de la misma. Es decir, es una forma nica de programar el acceso a bases de datos desde Java, independiente del tipo de la base de datos. JDBC realiza llamadas directas a SQL. Para ms informacin sobre JDBC se puede consultar la direccin http://www.java.sun.com/products/jdbc/. Existen cuatro categoras de drivers que soportan la conectividad JDBC, por ejemplo: puente JDBC-ODBC, drivers de red, drivers nativos. En la prctica utilizaremos un driver 2

especfico que permite la comunicacin directa de JDBC con MySQL. Su nombre es MySQL Connector/J y es un driver nativo que convierte llamadas JDBC al protocolo de red utilizado por la base de datos MySQL. Se puede encontrar ms informacin en: http://www.mysql.com/products/connector-j/. Este driver es necesario tenerlo instalado en el cliente y cambiar la variable CLASSPATH para que contenga la ruta del fichero .jar o de las carpetas org y com del driver. Para utilizarlo desde un entorno como el Eclipse, es necesario cambiar las propiedades del proyecto y aadir el .jar del driver como un jar externo. Paquete java.sql Las clases que conforman el API JDBC se encuentran agrupadas en el paquete java.sql. Este paquete contiene clases para cargar los drivers, realizar las conexiones a las bases de datos, consultar los datos y manejar un conjunto de registros. Tambin posee las clases para el manejo de excepciones que se produzcan en el acceso a bases de datos. A continuacin mostramos un esquema en el cual se encuentran las interfaces y clases fundamentales del paquete java.sql. Clases del Paquete java.sql

La interfaz Driver es la interfaz que todos los drivers deben implementar. Cada driver que quiera ser utilizado para conectarse a una base de datos desde Java debe suministrar una clase que implemente la interface Driver. Cuando esta clase es cargada en la aplicacin de Java, esta debe crear una instancia de s misma y registrarse en el DriverManager. Para cargar y registrar un driver desde el cdigo se hace con: Class.forName("URL del Driver") La clase DriverManager proporciona el servicio bsico para manejar un conjunto de drivers JDBC. Como parte de su inicializacin, esta clase intenta cargar las clases driver referenciadas en la propiedad del sistema "jdbc.drivers". El mtodo ms importante de esta clase es getConnection, a travs de cual la clase DriverManager intentar localizar un driver apropiado entre los que estn cargados en el proceso de inicializacin y aquellos cargados explcitamente en el cdigo. A continuacin mostramos la sintaxis del mtodo fundamental de esta clase: DriverManager.getConnection(String URL, String usuario, String password)

Este mtodo intenta establecer la conexin a la URL dada y devuelve un objeto Connection como resultado. La interfaz Connection representa una conexin o sesin con una base de datos especfica. Las sentencias SQL son ejecutadas y retornan sus resultados dentro del contexto de una conexin. Una conexin a una base de datos permite acceder a la informacin contenida en las tablas, soporta la gramtica SQL, los procedimientos almacenados, etc. La clase Types define las constantes que se utilizarn para identificar tipos genricos SQL, estas constantes son llamadas tipos JDBC. Esta clase no puede ser instanciada. A continuacin describimos algunas de las constantes que representan los tipos ms usados y su tipo equivalente en Java. Types.BITTypes.TINYINTTypes.SMALLINTTypes.INTEGER Types.BIGINTTypes.FLOATTypes.REAL Types.DOUBLE Types.NUMERIC Types.DECIMALTypes.CHAR Types.VARCHAR Types.LONGVARCHAR Types.DATE Types.TIM Types.BINARYTypes.VARBINARY boolean byte short int long double float double java.math.BigDecimal java.math.BigDecimal java.lang.String java.lang.String java.lang.String java.sql.Date java.sql.Time byte [] byte []

Las clases Date y Time se utilizan para representar los valores de fecha y hora desde el cdigo de Java permitiendo a JDBC identificarlos como SQL DATE y SQL TIME. La forma de representacin es especificando el valor de la fecha o la hora en milisegundos pasados desde el 1 de Enero de 1970. Las interfaces DatabaseMetaData y ResulSetMetaData permitirn obtener informacin referente al diseo y estructura de la base de datos y de los ResultSet que se obtengan respectivamente. La clase SQLException representa a las excepciones relacionadas con el acceso a base de datos y proporciona informacin acerca del error que ha ocurrido. Pasos para crear una aplicacin JDBC a) Cargar el driver JDBC. b) Conectarse a la Base de Datos utilizando la clase Connection. c) Crear sentencias SQL, utilizando objetos de tipo Statement. d) Ejecutar las sentencias SQL a travs de los objetos de tipo Statement. e) En caso que sea necesario, procesar el conjunto de registros resultante utilizando la clase ResultSet. Cargar el driver JDBC

Para conectarse a una base de datos a travs de JDBC desde una aplicacin Java, lo primero que se necesita es cargar el driver que se encargar de convertir la informacin que se enva a travs de la aplicacin a un formato que lo entienda la base de datos. Esta parte del cdigo sera la nica que dependera del tipo de driver y del tipo de base de datos. La sintaxis para cargar el driver es: Class.forName("Clase del driver").newInstace(); Por ejemplo, si el driver que se emplea es el puente JDBC-ODBC, entonces el cdigo para cargarlo sera: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); En esta prctica utilizaremos el driver nativo MySQLConector/J para acceder a MySQL. entonces el cdigo ser: Class.forName("com.mysql.jdbc.Driver").newInstance(); El cdigo para cargar el driver podra lanzar una excepcin de tipo ClassNotFoundException que debe ser capturada. Recordamos que este driver es necesario tenerlo instalado en el cliente y cambiar la variable CLASSPATH para que contenga la ruta del fichero .jar o de las carpetas org y com del driver. Para utilizarlo desde un entorno como el Eclipse, es necesario cambiar las propiedades del proyecto y aadir el .jar del driver como un jar externo. Conectarse a una Base de Datos Para conectarse a una fuente de datos especfica, una vez cargado el driver, se utiliza una URL que indicar la base de datos con la sintaxis: jdbc:subprotocolo:parmetros El subprotocolo indica una forma de conexin a una base de datos que puede ser soportada por uno o ms drivers. El contenido y sintaxis de los parmetros depende del subprotocolo. La sintaxis general de conexin es: Connection con = DriverManager.getConnection(URL, usuario, password) A continuacin se ir desarrollando un ejemplo con las diferentes funcionalidades para acceder a la base de datos DatosCoches. La conexin a la base de datos y la consulta de la misma se desarrollar en una clase java llamada AccesoDatos. Las pruebas se realizarn desde otra clase PruebaAccesoDatos que solo contendr una funcin main desde donde se llamar a todas las funciones de AccesoDatos. Por ejemplo, para conectarse a travs del driver de MySQL a la base de datos DatosCoches el cdigo sera: import java.sql.*; public class accesodatos{ Connection con; Statement st; ResultSet rs; public void abrirConexion() { try { 5

Class.forName("com.mysql.jdbc.Driver").newInstance(); con = DriverManager.getConnection(jdbc:mysql://localhost/DatosCoches"); System.out.println("Conexin a la BD"); } catch (Exception e) { System.out.println("Error en conexin "); }} //Para cerrar la conexin una vez terminadas las consultas public void cerrarconexion() { try { con.close(); System.out.println("Conexin cerrada"); } catch (SQLException e) { System.out.println("Error al cerrar conexin"); } } Consultar la Base de Datos Para recuperar informacin de una de base de datos se utiliza la clase Statement, cuyos objetos se crean a partir de una conexin y tienen el mtodo executeQuery para ejecutar consultas SQL de tipo SELECT devolviendo como resultado un conjunto de registros en un objeto de la clase ResultSet. Supongamos que se tiene una conexin a la base de datos DatosCoches cuyas tablas son Propietarios y Coches y que queremos obtener los registros de la tabla Coches ordenados segn el precio de mayor a menor, el cdigo sera: ... public void obtenerDatosTabla() { try { St = con.createstatement(); rs = st.executeQuery("SELECT * FROM Coches ORDER BY precio DESC"); System.out.println("Tabla abierta"); ... } catch (SQLException e) { System.out.println("Error al Abrir tabla "); } Una sentencia creada de esta forma devuelve un ResultSet en el que slo puede haber desplazamiento hacia adelante. Para luego acceder al conjunto de registros que se encuentran en el ResultSet, es necesario el mtodo next del objeto ResultSet para movernos por los registros y mtodos especficos pata extraer la informacin de cada tipo de campo con la forma getXXXX. A continuacin mostramos una tabla con los mtodos de los tipos ms comunes:

getInt getLong getFloat getDouble getBignumgetBoolean getStringgetStringgetDate getTimegetTimesstampgetObject

INTEGER BIG INT REAL FLOAT DECIMAL BIT VARCHAR CHAR DATE TIME TIME STAMP cualquier tipo

Para cada mtodo getXXXX, el driver JDBC debe hacer conversiones entre el tipo de la base de datos y el tipo Java equivalente. El driver no permite conversiones invlidas aunque si permite que todos los tipos puedan ser ledos desde Java como cadenas con el mtodo getString. Por otra parte, cuando se recorre el ResultSet es necesario conocer cuando se llega al final del mismo y esto se controla con el mtodo next que adems de moverse al siguiente registro, devuelve falso cuando se ha pasado del ltimo registro. Un ejemplo de cdigo para recorrer un ResulSet visualizando su contenido por consola es: ... public void mostrarDatosCoches() { try { while (rs.next()) { String strMat = rs.getString("Matricula"); String strMarca = rs.getString("Marca"); int intPrecio = rs.getInt("Precio"); System.out.println(strMat + ", " + strMarca + ", " + intPrecio); } } catch (Exception e) { System.out.println("Error al visualizar datos"); } } Consultas de Actualizacin Para actualizar la base de datos con sentencias SQL de tipo UPDATE, INSERT o DELETE, es necesario al igual que en el caso de SELECT, tener una Connection y crear una Statement a partir de la misma. La diferencia es que en vez de llamar al mtodo executeQuery para ejecutar la consulta, se llama al mtodo executeUpdate que no devuelve un ResultSet como resultado, sino que devuelve la cantidad de registros afectados. A continuacin se muestran varios mtodos con ejemplos de este tipo de consultas.

//Mtodo para modificar la tabla Coches pasando la matrcula del //coche que se quiere modificar y el nuevo precio. Las cadenas en la //condicin es necesario ponerlas entre comillas simples. public void modificar(String m, int p) { try { Statement s2=con.createStatement(); s2.executeUpdate("Update Coches set Precio="+ p + " where Matricula like '" + m + "%'"); System.out.println("Elemento modificado correctamente"); // st.executeUpdate(); - parece que no va }catch (SQLException e) { System.out.println("Error al modificar"); } } //Mtodo para borrar el coche cuya matricula se pasa como argumento public void borrar(String m) { try{ Statement s2=con.createStatement(); s2.executeUpdate( "DELETE FROM Coches where Matricula like '"+m+"%'"); System.out.println("Elemento Borrado"); }catch(SQLException e) { System.out.println("Error al Borrar"); } } //Mtodo que permite insertar un nuevo registro en la tabla Coches, //pasndole como argumento la matrcula, marca, precio del coche y //dni del propietario public void insertar(String m, String mar, int p, String d) { try{ Statement s1 = con.createStatement(); s1.executeUpdate( "INSERT INTO Coches (Matricula,Marca,Precio,DNI) values ('" + m + "', '" + mar + "'," + p + "'," + d + "')"); System.out.println("Elemento insertado"); 8

} catch(SQLException e) { System.out.println("Error al insertar "); }} Sentencias de tipo PreparedStatement Cuando se realiza la misma operacin varias veces, es mejor utilizar la clase PreparedStatement para una ejecucin eficiente. Esta eficiencia est dada porque la consulta que se ejecute a travs de un objeto de la clase PreparedStatement ser precompilada por el motor SQL de la fuente de datos a la cul se accede. Esta clase tambin permite una forma ms cmoda de ejecutar consultas a las cuales hay que pasar muchos parmetros. En estas consultas, los signos de interrogacin representan los parmetros. Para sustituir cada signo de interrogacin se utiliza un mtodo setXXXX(pos, valor) cuyo nombre depende del tipo del parmetro. El argumento pos indica la posicin del signo de interrogacin que se quiere sustituir, empieza en 1. //Mtodo para insertar un registro en la tabla Propietarios. Los //argumentos del mtodo son el DNI, nombre y edad. public void insertar(String dni, String n, int ed) { try { PreparedStatement ps = con.prepareStatement( "insert into Propietarios values (?,?,?) "); ps.setString(1, dni); ps.setString(2, n); ps.setInt(3, ed); //En este caso, el mtodo executeUpdate devuelve la cantidad de //elementos insertados. if (ps.executeUpdate()!=1){ throw new Exception("Error en la Insercin"); }catch (Exception e) { System.out.println("Error al Insertar "); }} Utilizacin de Metadata Como ya fue comentado anteriormente, existen clases en el paquete java.sql que permiten acceder a la informacin sobre el diseo y la estructura de la base de datos como un todo o de un ResultSet obtenido a partir de una consulta concreta. A este tipo de informacin se le llama metadata y las clases que nos permitirn obtenerlo son DatabaseMetaData y ResultSetMetaData. 9

Informacin de una Base de Datos Cuando se necesita conocer sobre las capacidades, o el vendedor de una base de datos, se puede preguntar al objeto Connection por su metadata. Existen muchas preguntas que se pueden hacer, entre ellas tenemos el tipo base de datos, la cantidad mxima de conexiones que permite la base de datos, etc. El fragmento de cdigo que se encuentra a continuacin, muestra como obtener esta informacin. ... Connection con = DriverManager.getConnection("...DatosCoches"); DataBaseMetaData dbMet = con.getMetaData(); if (dbMet==null) System.out.println("No hay informacin de MetaData"); else { System.out.println("Tipo de la BD: " + dbMet.getDataBaseProductName()); System.out.println("Versin : " + dbMet.getDatabaseProductVersion()); System.out.println("Cantidad mxima de conexiones activas: " + dbMet.getMaxConnectios()); } Informacin de un ResultSet Se puede obtener informacin de la estructura de un conjunto de registros resultantes de una consulta. Esto puede ser muy til para acceder a tablas de una base de datos de las cuales no se tenga informacin sobre su estructura. Utilizando la clase ResultSetMetaData podremos determinar la cantidad de columnas o campos que contiene un ResultSet, el tipo y nombre de cada campo, sin el campo es solo lectura, etc. La funcin siguiente muestra la estructura de una tabla que le pasemos como argumento. public void estructuraTabla(String strTbl) { try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("Select * from " + strTbl); //Obtiene el metadata del ResultSet ResultSetMetaData rsmeta = rs.getMetaData(); //Obtiene la cantidad de columnas del ResultSet int col = rsmeta.getColumnCount(); for (int i = 1; i <= col; i++) { System.out.println("Campo " + //Devuelve el nombre del campo i rsmeta.getColumnLabel(i) + "\t" //Devuelve el tipo del campo i + "Tipo: " + rsmeta.getColumnTypeName(i)); } 10

catch (Exception e) { System.out.println("Error en Metadata "); }} Tambin es posible mediante la utilizacin de la informacin del ResultSetMetaData mostrar la informacin de cualquier tabla sin tener la estructura previamente. public void verCualquierTabla(String strTbl) { try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("Select * from " + strTbl); ResultSetMetaData meta = rs.getMetaData(); int col = meta.getColumnCount(); //Mientras haya registros while (rs.next()) { for (int i = 1; i <= col; i++) { //Mostrar el dato del campo i System.out.print(rs.getString(i) + "\t"); } System.out.println(""); } }catch (Exception e) { System.out.println("Cualquier " + e.toString()); } Clase que prueba el acceso a datos Para probar todas las funciones que se han hecho en la clase AccesoDatos se puede desarrollar la clase PruebaAccesoDatos con una funcin main: public class PruebaAccesoDatos { public static void main(String[] args) { AccesoDatos bd = new AccesoDatos(); bd.abrirConexion(); //Tabla Coches bd.obtenerDatosTabla(); bd.mostrarDatosCoches(); bd.insertar("VA-1235","BMW",6000,"1A"); bd.modificar("MA-1111",8000); bd.borrar("MA-2222"); bd.obtenerDatosTabla(); bd.mostrarDatosCoches(); //Tabla propietarios bd.insertar("1D","Andres",36); bd.verCualquierTabla("Propietarios"); bd.estructuraTabla("Propietarios"); }}

11