Elaboración Material didáctico con Nuevas Tecnologías como apoyo a la materia Bases de Datos I
 sobre JDBC (Conecividad de base de datos con Java) para la materia de Bases de Datos I de la Licenciatura en Ciencias de la Computación
María de Guadalupe Cota Ortiz
Materia: Bases de Datos (Licenciatura en Ciencias de la Computación)

Objetivo: Apoyar el aprendizaje de métodos de conectividad a bases de datos con Java.
Tema: 	Conectividad de Java con Bases de Datos en Mysql

Software educativo elaborado como apoyo para conectividad con bases de datos utilizando java, utilizándose como práctica del alumno durante el curso.

GUION:

1.	Operaciones con Java y JDBC 
1.1 Introducción
 	1.2 Paquete java.sql 
	1.3 Conexión a la base de datos
1.4 Pasos para crear una aplicación JDBC 
•	Cargar el driver JDBC 
•	Conectarse a una Base de Datos
•	Aplicación de Querys (Consultar) para inserción, eliminación, actualización y consulta en la Base de Datos  y ejemplo de implementación de métodos proporcionados por java.sql para el Sistema Gestor de Base de datos Mysql.
	1.5 Descripción del comportamiento de los métodos proporcionados por java.sql
	2. Creación de una Base de Datos y sus tablas por medio de un fichero script.
        3. Referencias bibliográficas.

1. Operaciones con Java y JDBC 

	1.1 Introducción 

	Java es un lenguaje de programación que proporciona medios para conectividad con bases de datos, lo cual permite a las aplicaciones interactuar directamente con motores de bases de datos relacionales [1]

	A continuación se hace una descripción general de la organización de clases y 	métodos del lenguaje Java a través del driver MySQL Connector/J,  proporcionado 	para la 	conectividad de java con bases de datos [2]:

	JDBC es un API de Java que permite ejecutar sentencias SQL. El driver viene integrado en el software de instalación de Java, sin embargo algunas versiones antiguas requieren que el driver sea colocado en las carpetas de instalación de java.

	1.2 Paquete java.sql 

	Las clases del API JDBC se encuentran en el paquete java.sql. Este paquete contiene clases para cargar los drivers, realizar conexiones a bases de datos, consultar  datos y manejar un conjunto de registros. También incluye el manejo de excepciones que se produzcan en el acceso a bases de datos. 

	Cuando la clase Driver es cargada en la aplicación de Java, ésta debe crear una instancia y registrarse en el DriverManager. Para cargar y registrar un driver desde el código se utiliza el siguiente código: 

		Class.forName("URL  del Driver") ;

	El lenguaje estructurado de consultas SQL es utilizado para acceder a la información contenida en la base de datos.

	1.3 Conexión a la base de datos

	El método getConnection, de la clase DriverManager intenta localizar un driver apropiado que fueron cargados en el proceso de inicialización y aquellos cargados explícitamente en el código. 

	La sintaxis para aplicar la instrucción de conectividad es la siguiente [2]:

DriverManager.getConnection(String URL, String usuario, String password)

	Ejemplo:

	public void connectToAndQueryDatabase(String username, String password) {
	   // cargar el driver
	   Connection con = DriverManager.getConnection(
               "jdbc:myDriver:myDatabase",username, password);
	   // Crear una instancia para conexión con la base de datos
	   Statement stmt = con.createStatement();
	   // Ejecutar una consulta
	   ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");

    	   while (rs.next()) {
	        int x = rs.getInt("a");
	        String s = rs.getString("b");
	        float f = rs.getFloat("c");
	     }
	}

	Este método intenta establecer la conexión a la URL (dirección) indicada, y devuelve un objeto Connection como resultado. 

	1.4 Pasos para crear una aplicación JDBC 

	a)    Cargar el driver JDBC 

	Para conectarse a una base de datos a través de JDBC desde una aplicación Java, lo primero que se requiere es cargar el driver que será el 'puente' para interactuar entre la aplicación y la 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 código para cargarlo sería: 

			Class.forName("com.mysql.jdbc.Driver").newInstance(); 

	El código para cargar el driver podría lanzar una excepción de tipo ClassNotFoundException que debe ser capturada. 

	b)   Conectarse a una Base de Datos 

		Para conectarse a una fuente de datos específica, una vez que se ha cargado el driver, se utiliza una dirección (URL), que indicará la base de datos con la sintaxis: 

			Connection con = DriverManager.getConnection(URL, usuario, password) 

            c)   Aplicación de Querys (Consultar) para inserción, eliminación, actualización y consulta en la Base de Datos  y ejemplo de implementación de métodos proporcionados por java.sql para el Sistema Gestor de Base de datos Mysql
	A continuación se irá desarrollando un ejemplo, incluyendo funcionalidades para acceder a la base de datos automoviles. 

	Para ello se utilizan dos archivos:
		accesodatos
		pruebaaccesodatos

•	La conexión a la base de datos y la consulta de la misma se desarrollará en una clase java llamada accesodatos. 

		Código de prueba de accesodatos:

import java.sql.*; 

public class accesodatos { 

// INSTANCIACIÓN DE VARIABLES DE CONEXIÓN
	 Connection con; 
	 Statement st; 
        	ResultSet rs; 

// ABRIR CONEXION       	

public void abrirConexion() { 
         try {
    	Class.forName("com.mysql.jdbc.Driver").newInstance(); 
	con = DriverManager.getConnection("jdbc:mysql://localhost/automoviles", 			"lupita","lupita"); 
      	 System.out.println("Conexion a la BD"); 
            }
         catch (Exception e) {
                System.out.println("Error en conexion ");
            } 
 } 

 //CERRAR LA CONEXION 
 public void cerrarconexion()   { 
         try { 
                con.close(); 
                System.out.println("Conexion cerrada"); 
          } 
          catch (SQLException e) { 
                  System.out.println("Error al cerrar conexion"); 
          } 
 }

//ACCESO A TABLA DE BASE DE DATOS 

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

//MOSTRAR DATOS

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

//MODIFICAR DATOS

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");
       }
       catch (SQLException e) { 
	  System.out.println("Error al modificar"); 
       } 
} 

//ELIMINAR DATOS
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"); 
       }
}

//INSERTAR DATOS 
public void insertar(String m, String mar, int p, String d) { 
        try { 
	PreparedStatement ps = con.prepareStatement("insert into coches values (?,?,?) ");	ps.setString(1, m); 
	ps.setString(2, mar); 
	ps.setInt(3, p); 
	ps.setString(1, d); 
	System.out.println("Elemento insertado"); 
       } 
       catch(SQLException e) { 
	System.out.println("Error al insertar "); 
      } 
}

//Método para insertar un registro en la tabla propietarios. Los
//argumentos del método son el id, nombre y edad. 
public void insertar(String dni, String n, int ed) { 
      try { 
	PreparedStatement ps = con.prepareStatement("insert into propietarios values (?,?,?) ");
 	ps.setString(1, id); 
	ps.setString(2, n); 
 	ps.setInt(3, ed); 
	//En este caso, el método executeUpdate devuelve la cantidad de
	//elementos insertados. 
	if (ps.executeUpdate()!=1){ 
		throw new Exception("Error en la Inserción"); 
	}
	System.out.println("Elemento insertado ");
        }
       catch (Exception e) {
	System.out.println("Error al Insertar "); 
       } 
} 

//OBTENER DICCIONARIO DE TABLA

public void estructuraTabla(String strTbl) {
        try { 
	Statement st = con.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 " + rsmeta.getColumnLabel(i) + "\t" + "Tipo: " + 			rsmeta.getColumnTypeName(i));
	      //Devuelve el nombre del campo i 
	     //Devuelve el tipo del campo i + "Tipo: " + rsmeta.getColumnTypeName(i));
	}
       } 
      catch (Exception e) { 
	  System.out.println("Error en Metadata "); 
      } 
} 

//VISUALIZAR CONTENIDO DE TABLA

public void verCualquierTabla(String strTbl) { 
      try { 
	Statement st = con.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()); 
     }
  }
}

 
•	Las pruebas se realizarán desde otra clase pruebaaccesodatos. 

		Código de prueba de pruebaaccesodatos:

import java.io.*;

public class pruebaaccesodatos { 

	public static void main(String[] args) { 
		accesodatos bd = new accesodatos(); 
		bd.abrirConexion(); 
		//Tabla Coches 
		bd.obtenerDatosTabla(); 
		bd.mostrarDatosCoches(); 
		bd.insertar("TT-1111","TTT",7000,"TT"); 
		bd.modificar("MA-1111",8000); 
		bd.borrar("MA-2222"); 
		bd.obtenerDatosTabla(); 
		bd.mostrarDatosCoches(); 
		//Tabla propietarios 
		bd.insertar("1D","Guadalupe",36); 
		bd.verCualquierTabla("propietarios"); 
		bd.estructuraTabla("propietarios"); 
	} 
}

1.5 Descripción del comportamiento de los métodos proporcionados por java.sql

	Para recuperar información de una de base de datos se utiliza la clase Statement, cuyos objetos se crean a partir de una conexión y tienen el método executeQuery para ejecutar consultas SQL de tipo SELECT devolviendo como resultado un conjunto de registros en un objeto de la clase ResultSet. 

	Un ejemplo de código para recorrer un ResulSet visualizando su contenido por consola se puede consultar en el método obtenerDatosTabla() de la clase accesodatos cuyo código fue presentado en el punto anterior.
	
	Una sentencia creada de esta forma devuelve un ResultSet en el que sólo puede haber desplazamiento hacia adelante. 

	Para acceder al conjunto de registros que se encuentran en el ResultSet, es necesario utilizar el método next para realizar desplazamiento por los registros pata extraer la información de cada tipo de campo con la forma getXXXX. A continuación se muestra una tabla con los métodos de los tipos más comunes: 

	getInt 		getLong 		getFloat 		getDouble 	getBignum	getBoolean 		getStringgetStringgetDate 	getTimegetTimesstampgetObject

	Para cada método 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 no válidas aunque permite que todos los tipos puedan ser leídos desde Java como cadenas con el método getString. 

	Por otra parte, cuando se recorre la tabla con el método ResultSet, es necesario saber cuándo se llega al final del mismo, y esto se controla con el método next que además de moverse al siguiente registro, devuelve valor de falso cuando se ha llegado al final de los registros. 

	Un ejemplo de código para recorrer un ResulSet visualizando su contenido por consola se puede consultar en el método mostrarDatos() de la clase accesodatos cuyo código fue presentado en el punto anterior.
 
Consultas de Actualización  

	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 instancia de conexión con Connection, y crear un Statement a partir de la misma. La diferencia es que en vez de llamar al método executeQuery para ejecutar la consulta, se llama al método executeUpdate que no devuelve un ResultSet como resultado, sino que devuelve la cantidad de registros afectados. 

	Un ejemplo de código para modificar, borrar o insertar datos se puede consultar en el método modificars(), borrar() e insertar() de la clase accesodatos cuyo código fue presentado en el punto anterior.

	 Sentencias de tipo PreparedStatement 

	Cuando se realiza la misma operación varias veces, es mejor utilizar la clase PreparedStatement para una ejecución eficiente. Esta eficiencia está dada porque la consulta que se ejecute a través de un objeto de la clase PreparedStatement será precompilada por el motor SQL de la fuente de datos a la cual se accede. 

	Esta clase también permite una forma más fácil de ejecutar consultas a las cuales hay que pasar muchos parámetros. 

	En estas consultas, los signos de interrogación representan los parámetros. Para sustituir cada signo de interrogación se utiliza un método setXXXX(pos, valor) cuyo nombre depende del tipo del parámetro. El argumento pos indica la posición del signo de interrogación que se quiere sustituir, empieza en 1. 

	Un ejemplo de código para insertar datos se puede consultar en el método insertar() de la clase accesodatos cuyo código fue presentado en el punto anterior.

	Utilización de Metadata 

	Como ya fue comentado anteriormente, existen clases en el paquete java.sql que permiten acceder a la información sobre el diseño 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 información se le llama metadata y las clases que nos permitirán obtenerlo son DatabaseMetaData y ResultSetMetaData. 

	Un ejemplo de código para obtener metadatos de una tabla se puede consultar en el método estructuraTabla() de la clase accesodatos cuyo código fue presentado en el punto anterior.

	 Información de un ResultSet 

	Se puede obtener información 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 información 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 función siguiente muestra la estructura de una tabla que le pasemos como argumento. 

	Un ejemplo de código para obtener metadatos de una tabla se puede consultar en el método estructuraTabla() de la clase accesodatos cuyo código fue presentado en el punto anterior.

	También es posible mediante la utilización de la información del 	ResultSetMetaData mostrar la información de cualquier tabla sin tener la estructura 	previamente.  

	Un ejemplo de código para obtener metadatos de una tabla se puede consultar en el método vercualquierTabla() de la clase accesodatos cuyo código fue presentado en el punto anterior.

2. Creación de una Base de Datos y sus tablas por medio de un fichero script 

	Se puede crear un fichero script que contenga todos los comandos a ejecutar. 

	Ejemplo 1

	Nombre del archivo: 		automoviles.sql.
	Base de datos a crear: 		automoviles
	Tablas: 			Persona y automovil

	'persona' tiene como llave primaria el campo 'id_persona', que es utilizado como 	llave foránea en la tabla 'automovil', la cual tiene a su vez como llave primaria el 	campo 'id_automovil'.

	CREATE DATABASE automoviles; 

	USE automovil; 
	CREATE TABLE persona (id_persona VARCHAR(10) PRIMARY KEY, 
	nombre VARCHAR(40), 
	edad INTEGER); 
	CREATE TABLE automovil (id_automovil VARCHAR(10) PRIMARY KEY,
		matricula VARCHAR(10) ,
	marca VARCHAR(20),
	precio INTEGER, 
	id_persona VARCHAR (10), 
	FOREIGN KEY (id_persona) references persona); 

	INSERT INTO persona values('1','Jose Munguia Soto',30); 
	INSERT INTO persona values('2','Rafael Perez Lopez',40); 
	INSERT INTO persona values('3','Rosa Castro Servin',50); 
	INSERT INTO persona values('4','Hilario Olea Mazon',50); 
	INSERT INTO persona values('5','Manuel Higuera Maldonado',50); 
	INSERT INTO persona values('6','Hortencia Figueroa Morfin',50); 
	INSERT INTO automovil values('1','VTU-5432','Neon',20000,'1'); 
	INSERT INTO automovil values('2','MTV-3434','Malibu',40000,'3'); 
	INSERT INTO automovil values('3','TVA-3439', 'Honda', 60000,'2'); 
	INSERT INTO automovil values('4','RTV-3211', 'Camaro',30000,'5'); 
	INSERT INTO automovil values('5','LVA-4395', 'Volkswagen',20000,'5'); 
	INSERT INTO automovil values('6','ITR-6547', 'Honda', 60000,'6'); 

	#Verificar información de diccionario
		explain persona;
		describe automovil; 

	 #Verificar información insertada a través de consulta
		Select * from persona; 
		Select * from automovil; 
		Select * from persona p, automovil a where p.id_persona = a.id_automovil; 

	El script puede ser importado a través del mecanismo del Sistema Gestor de Bases de Datos (SGBD) correspondiente (Oracle, Mysql, SqlServer, PostgreSQl, etc.). Cabe señalar que una vez ingresado el script hay que verificar si el SGBD permite la implementación de Integridad Referencial para relacionar llaves primarias con llaves foráneas. En el caso de MySql hay que utilizar el indexamiento 'innobd' que es el único método de indexamiento que permite esta operación.

	Creación de una base de datos en MySQL 

	MySQL es un servidor de bases de datos  que permite la creación de bases de datos relacionales que pueden ser consultadas a través de SQL (Structure Query Language). 

•	Referencias de instalación: 

 http://www.mysql.com. 

•	Iniciar y utilizar el servidor MySQL 

	Instrucción para iniciarlo

C:\> C:\mysql\bin\mysqld-max-nt --standalone
		Ejecutar mysqld con --standalone --debug. permite guardar un 			fichero de registro llamado C:\mysqld.trace el cual 					debería contener la razón por la cual mysqld no se inicia.

Instrucción para conectarse 

  	shell> mysql -u <usuario>
	(Enseguida se pedirá la contraseña correspondiente. Cuando el usuario es 'root' y MySql está recién instalado solo se oprime la tecla 'enter' para indicar que la contraseña está en blanco o no existe)

	Instrucción para desconectarse 

  	mysql> QUIT 

Instrucción para finalizar el servicio de MySql

	 mysql>  shutdown

3. Referencias bibliográficas:

[1]	Conectividad java-bases de datos. http://www.slideshare.net/javi2401/java-y-bases-de-datos-presentation.
[2]	Tutoriales sobre JAVA y JDBC. http://docs.oracle.com/javase/tutorial/jdbc/