Usuario:ManuelRomero/jdbc

De WikiEducator
Saltar a: navegación, buscar

JDBC

  • Como ya tenemos claro el concepto vamos a utilizarlo
  • JDBC es una parte del API de SDK de java
  • JDBC Es una especificación de un conjunto de clases y métodos que permiten acceder desde un programa JAVA a una base de datos
  • Gracias a este API, y una vez que tenemos conexión con la base de datos gestionar la base de datos como si lo hiciéremos desde el propio gestor.
JDBC hace posible estas tres cosas
Establece una conexión con la base de datos.
Envía sentencias SQL
Procesa los resultados.

Jdbc1.png

  • Para conectar a una BBDD necesitamos un driver


Icon define.gif

Definición

Este software que normalmente lo facilitará el fabricante, nos va a permitir establecer una conexión para poder manipular la base de datos


  • Es la misma idea que si compramos un hardware y el fabricante me facilita el driver para poderlo usar en mi sistem
  • Una vez que tengo el driver Las clases con sus métodos que me permite gestionar la base de datos , están bajo el paquete java.sql

Clase conexion

Ejemplo a realizar

  1. concectarnos a una base de datos llamada concesionario
  2. propietario de la base de datos manolo sin pass
  3. ip de la máquina donde está el gestor de la base de datos (será dhcp, ponerlo en la pizarra)

Se trata de hacer un interfaz gráfico que nos permita ir navegando por los diferentes registros de la tabla clientes La tabla tiene 5 campos

Debemos realizar el diagrama de clases y la implementación, funcionando

Acciones a realizar

Acciones a realizar
Primero cargar el driver

http://dev.mysql.com/downloads/connector/j/5.0.html



Icon qmark.gif

Pregunta

Donde debemos ubicarlo


Tres posibilidades:
Poníendolo en DIR_HOME_JAVA/lib/ext/ (Problema SF montado en sólo lectura para nuestro sistema)
Incluyéndolo en le CLASSPATH
Añadiéndolo al directorio de nuestro proyecto (esta será nuestra opción)
Buscar la opción en eclipse de java buil path o via de construcion de java

Conectar con la BD

Cargamos el driver

 //El nombre de cada driver depende de la BD con la que nos conectamos
 //Consultar información en la página oficial del gestor de BD
 String Driver "com.mysql.jdbc.Driver";  	
 Class.forName(Driver);

Existen tres clases fundamentales para una aplicación básica Connection ==> Conexión

 String BD = "jdbc:mysql://localhost/concesionario" //Notación normalizada para identificar a una base de datos 
 String usuario = "manolo";
 String pass ="";
 Connection con = DriverManager.getConnection(BaseDatos,usuario,pass);

Statement ==> Una instruccion y orden que queremos enviar a una base de datos p.e. una sentencia SQL

  Statement  instruccion = con.createStatement();

//Podemos pasar como parámetro al construcctor como queremos que sea el resultSet que ejecute la consulta p.e si las modificaciones que hagamos que se realicen ad-hoc en la BD

DIFERENTES MODOS DE USAR RESULTSET
TIPOS DE RESULTSET DESCRIPCION
TYPE_FORWARD_ONLY Sólo se puede recorrer hacia adelante y no es sensible a cambios en base de datos.
TYPE_SCROLL_INSENSITIVE Tiene desplazamiento (adelante/atrás), pero es insensible a cambios en base de datos.
TYPE_SCROLL_SENSITIVE Tiene desplazamiento (adelante/atrás) y es sensible a cambios en base de datos.

ResultSet ==> Un cursor f

String consulta = "select * from clientes"
ResultSet rtdo = instruccion.executeQuery(consulta);


  • implementaremos una clase para conectarnos a una base de datos

Qué es un resultSet

  • Es una clase que contiene información de una consulta
  • No solo el conjunto de filas o registros que se conoce como cursor
  • También información sobre la consulta Números de filas', campos, nombre de cada atributo, ...
  • Además en cada momento tenemos referenciado un registro del cursor

Resultset.png

Métodos para navegar
Cuando abrimos el cursor el puntero referencia a antes del primero
Mueven el cursor al registro indicado (siguiente, anterior, primero, último) o retornan null  si no han podido hacerlo
next()
previous()
first()
last()
beforeLast();
Método para saber dónde estamos

Retorna un booleado true o false

isFirst() 
isLast()
Métodos para extraer un campo de un registro

Se extraen cada campo del registro acutal

getInt(1) o getInt("numSocio"); ==> Me devuelve el valor entero del registro actual del campo numSocio
getString(2) o getString("nombre");
getObject(1) obtener el valor del campo 1 como de tipo object.
Meta información de la consulta

Me informa de número de filas, número de columnas, nombre de cada campo o atributo, http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/ResultSetMetaData.html

 ResultSet rs = stmt.executeQuery("SELECT * from clientes"");
    ResultSetMetaData rsmd = rs.getMetaData();
    int numberDeColumns = rsmd.getColumnCount();

getColumnName

    boolean b = rsmd.isSearchable(1);

JTable y DefaultTableModel

  • Definimos un objeto de swing para almacenar en una tabla el resultado de una consulta
  • El objeto es JTable este objeto se puede enlazar con una consulta para visualziar el contenido del resultset.
  • Puedo definir la estructura y comportamiento de la tabla con el objeto

y tener toda su funcionalidad es instanciar un DefaultTableModel y meterlo en el JTable, en el constructor También añadimos un JScollPane por si no cabe la tabla para poder moverme por ella

Usaremos las siguientes clases

 //Objetos para el jTable y DefaultTableModel
 private DefaultTableModel modelo = new DefaultTableModel();
 private JTable taCuentas = new JTable(modelo);
 private JPanel pCuentas;
 JScrollPane scroll;

y las instanciamos al cargar la interfaz

 
	 modelo = new DefaultTableModel();
	 taCuentas = new JTable(modelo);
	 taCuentas.setPreferredScrollableViewportSize(new Dimension(500,50));
	 scroll = new JScrollPane(taCuentas);
         pCuentas.add(scroll)
Importante es observar que en realidad el scroll es un contenedor que contiene el JTable basado en un DefaultTableModel

Ahora cualquier cambio que hagamos sobre el modelo se reflejará automáticamente sobre el Jtable asociado

Acciones para cargar el jtable

  • Después de haber cargado un socio , invocamos a un metodo que podemos llamar rellenaCuentaSocio(int socio)
  • A este método le pasamos un socio
  • vemos el código y lo comentamos
private void rellenaCuentasSocio(int numSocio){
	 //Obetener información de un meta
try{
	//Para inicializar el modelo a 0 filas y 0 columnas 
	//(Para perder los datos anteriores)
	modelo.setRowCount(0);
	modelo.setColumnCount(0);
 
	//Creamos un nuevo resultset para recuperar en una consulta
	//Las cuentas del socio actual
 	 ResultSet ccc;
	 ccc=conexion.hacerConsulta("Select * from cuentaBancaria where cliente = "+numSocio);
 
	 //Necesitamos información sobre la consulta hecha
	 //
	 ResultSetMetaData rsmd = ccc.getMetaData();
 
	 //Información de la consulta del número de filas
	 int columnas= rsmd.getColumnCount();
	 System.out.println("Se han encontrado "+columnas +"columnas");
 
	 //Alternativa para rellenar la cabecera de la tabla
	 /*
	   Object[] etiquetas = new Object[columnas];
       for (int i = 0; i < columnas; i++)
       {
           etiquetas[i] = rsmd.getColumnLabel(i + 1);
       }
 
       // Se meten las etiquetas en el modelo. El numero
       // de columnas se ajusta automáticamente.
       modelo.setColumnIdentifiers(etiquetas);
       */
	 //Rellenamos en la tabla con tantas columnas como campos tiene la consulta
 
	   for (int i=1;i<=columnas;i++){
		   //Cada columna que rellenamos ponemos el título del campo
		   modelo.addColumn(rsmd.getColumnName(i));
		   System.out.println("Rellenando el campo"+rsmd.getColumnName(i));
	   }
 
       //Ahora cargamos el contenido de la consulta en la tabla
	   while (ccc.next()){
		   // Se crea un array que será una de las filas de la tabla.
		   Object [] fila = new Object[columnas]; 
 
		   // Se rellena cada posición del array 
		   //Con cada fila de la consulta
		   for (int i=0;i<columnas;i++)
		      fila[i] = ccc.getObject(i+1); 
 
		   // Se añade al modelo la fila completa.
		   modelo.addRow(fila);
	   }
 
	 }catch(SQLException e){
		   System.out.println("Error en la tablita Se han encontrado "+e.getMessage());
 
	 }
 }
}//End class

Podemos añadir columnas directamente en el modelo

modelo.addColumn("etiqueta columna 1");
modelo.addColumn("etiqueta columna 2");

Podemos añadir datos directamente en el modelo, así como borrarlos o modificarlos

Object [] fila = new Object[2];
fila[0] = "dato columna 1";
fila[1] = "dato columna 3";
modelo.addRow ( fila ); // Añade una fila al finalç

Modificar una posición concreta de una celda

modelo.setValueAt ("nuevo valor", 0, 1); // Cambia el valor de la fila 1, columna 2.

Borrar una fila concreta

modelo.removeRow (0); // Borra la primera fila

Todo lo que hagamos se reflejará de inmediato en el JTable.

Obtener fila y columna del JTable en la que se hace click

A veces nos interesa seleccionar una fila del JTable para hacer algo con ella (sacar un menú, recoger datos para mostrarlos en otro sitio, etc).

Una forma de hacerlo es añadiendo un MouseListener al JTable, de esta manera

tabla.addMouseListener(new MouseAdapter()

  {
     public void mouseClicked(MouseEvent e) 
     {
        int fila = tabla.rowAtPoint(e.getPoint());
        int columna = tabla.columnAtPoint(e.getPoint());
        if ((fila > -1) && (columna > -1))
           System.out.println(modelo.getValueAt(fila,columna));
     }
  });

</pre>

Hemos añadido un MouseAdapter para no tener que implementar todos los métodos del MouseListener.

Con el método tabla.rowAtPoint() es posible enterarnos en qué fila de del JTable ha ocurrido el evento del ratón (el click en este caso). Para ello basta llamar a este método pasándole las coordenadas x,y del evento de ratón, que se obtienen con el método e.getPoint().

Una vez que sabemos la fila, debemos comprobar si es mayor que -1. El método rowAtPoint() nos devuelve -1 si pinchamos en el JTable, pero fuera de cualquier fila. Es el caso de que el JTable tenga un tamaño en pixels superior al que le corresponde según su número de filas.

Lo mismo vale para columnAtPoint().

Una vez que tenemos la fila y sabemos que no es -1, es fácil a través del modelo obtener los datos correspondientes. En este caso se escribe por pantalla con un System.out.prinln() el valor de la fila y columna que se ha seleccionado.

Hacer que una celda del JTable no sea editable

Si usamos DefaultTableModel las celdas del JTable son editables por defecto. A veces esto no nos interesa y JTable no tiene métodos para impedirlo. La forma de decidir qué celdas son o no editables es hacer nuestro propio modelo de datos, nuestro TableModel. La forma sencilla de hacerlo es heredar de DefaultTableModel y redefinir el método isCellEditable() para que sirva a nuestros propositos

public class MiModelo extends DefaultTableModel
{
   public boolean isCellEditable (int row, int column)
   {
       // Aquí devolvemos true o false según queramos que una celda
       // identificada por fila,columna (row,column), sea o no editable
       if (column == 3)
          return true;
       return false;
   }
}

En este ejemplo, hemos creado nuestro propio modelo de datos que hace que la columna 4 (los índices empiezan en cero) de la tabla sea editable y el resto no. Ahora simplemente instanciamos el JTable usando este modelo y rellenamos los datos igual que antes

 MiModelo modelo = new MiModelo();
 JTable tabla = new JTable(modelo);


Cambiar el tipo de dato con DefaultTableModel

DefaultTableModel por defecto le dice al JTable que todos los datos que tiene son Object. A veces, porque queramos cambiar el TableCellRenderer o cualquier otro motivo, nos interesa que determinadas columnas se consideren como Boolean, como Integer o cualquier otro tipo de dato.

Para modificar esto, tenemos que crearnos nuestro propio modelo de Datos. La forma más sencilla es heredar de DefaultTableModel y redefinir el método getColumnClass().

public class MiModelo extends DefaultTableModel
{
   /** Primera columna Boolean, segunda Integer y el resto Object */
   public Class getColumnClass(int columna)
   {
      if (columna == 0) return Boolean.class;
      if (columna == 1) return Integer.class;
      return Object.class;
   }
}

En el ejemplo se ha hecho que la primera columna sea de Boolean, la segunda de Integer y el resto de Object.

Una cosa curiosa de los Boolean, es que el JTable al pintarlos los pone como JCheckBox.

Hacer visible una fila concreta del JTable dentro de un JScrollPane

Para que un JTable tenga barras de scroll y tenga una "cabecera" con las etiquetas de las columnas, es necesario meterla en un JScrollPane. Esto se puede hacer de dos formas.

JTable tabla = new JTable();
JScrollPane scroll = new JScrollPane(tabla);

o bien

JTable tabla = new JTable();
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(tabla);

es bastante habitual al principio equivocarse y usar el método add(), que NO funcionará correctamente

JTable tabla = new JTable();
JScrollPane scroll = new JScrollPane();

// Esto NO funciona.
scroll.add(tabla);

Cuando tenemos un JTable metido dentro de un JScrollPane, a veces queremos que las barras de scroll se desplacen para que una determinada celda sea visible.

No conozco una forma inmediata de hacerlo, pero una posible solución es esta.

Conexin.java

public class Conexion {
	Connection conexion;
	Statement instruccion;
	ResultSet consulta;
	String driver = "com.mysql.jdbc.Driver";
	String bd = "jdbc:mysql://localhost/concesionario";
	String usuario ="root";
	String pass ="";
 
	Conexion(){
		//primero cargamos el driver que previamente hemos descargado
		//De la página de la BD con la que vamos a conectar
		try{
		Class.forName(driver);
		//Conectar con la base de datos
		conexion = DriverManager.getConnection(bd,usuario, pass);
		System.out.println("Conectado!!!!!");
 
		instruccion = conexion.createStatement();
 
		consulta = instruccion.executeQuery("Select * from clientes");
 
		}catch(ClassNotFoundException e){
			System.out.println("Error clase no encontrada: "+e.getMessage());
		}
		catch (SQLException e){
			System.out.println("Error SQL : "+e.getMessage());
		}
 
	}
	public ResultSet getConsulta(String consulta){
		try{
		return instruccion.executeQuery(consulta);
		}catch(SQLException e){
			System.out.println("Error haciendo la consulta ");
		}
		return null;
	}
	public void desconectar (){
		try{
			conexion.close();
		}catch (SQLException e){
			System.out.println("Error desconectando con la BD");
		}
	}
}

consulta sql

create database concesionario;
use concesionario;
drop table clientes;
create table clientes(
numSocio  int ,
primary key(numSocio),
nombre varchar(20),
apellidos varchar(20),
direccion varchar(20),
dni varchar(10));
 
 
create table cuentaBancaria(
NumCuenta int,
cliente int,
primary key(NumCuenta,cliente),
foreign key (cliente) references clientes (numSocio),
banco int,
sucursal int,
control int ,
ccc int,
saldo int,
Observaciones varchar(255)
);
 
insert into clientes values(0,"Manuel","Romero","Casa de manolo", "11.111.111-A");
insert into clientes values(1,"Maria","Ruiz","Casa de Maria", "22.222.222.-B");
insert into clientes values(2,"Pilar","Molina","Casa de Pilar", "33.333.333.-C");
insert into clientes values(3,"Nieves","Esteban","Casa de Nieves", "44.444.444-D");
 
insert into cuentaBancaria values(0,0,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 0");
insert into cuentaBancaria values(1,0,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 1");
insert into cuentaBancaria values(2,0,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 2");
insert into cuentaBancaria values(3,0,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 3");
insert into cuentaBancaria values(0,1,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 0");
insert into cuentaBancaria values(1,1,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 1");
insert into cuentaBancaria values(0,2,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 0");
insert into cuentaBancaria values(1,2,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 1");
insert into cuentaBancaria values(2,2,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 2");
insert into cuentaBancaria values(3,3,1111,2222,33,4444444444,1000,"Observaciones de la cuenta 3");