miércoles, 9 de abril de 2008

* COMO CONECTAR BASES DE DATOS DESDE JAVA

1. CONECTAR BD ACCESS CON JAVA

JDBC y ODBC


La capacidad para acceder a bases de datos desde Java la ofrece la API JDBC (Java DataBase Conectivity). JDBC es un estándar para manejar bases de datos en Java. ODBC es un estándar de Windows para manejar bases de datos, de forma que cualquier programa en Windows que desee acceder a bases de datos genéricas debe usar este estándar. La necesidad de crear un estándar propio para acceder a bases de datos desde Java se explica porque el estándar ODBC está programado en C y un programa que use este estándar, por lo tanto, depende de la plataforma.

Controladores JDBC-ODBC

Necesitamos acceder a un origren de datos ODBC pero contamos con una API que usa el estándar JDBC. Para solventar este problema las empresas realizan drivers que traducen el ODBC a JDBC. Hay varios tipos de Driver, pero para nuestro ejemplo usaremos los llamados puentes JDBC-ODBC. Estamos de suerte porque el JDK de Windows incorpora el driver necesario para conectar bases de datos Access.

Crear un nuevo DSN (Data Source Name)

Para realizar la conexión a una base de datos ODBC necesitaremos crear un perfil DSN desde el panel de control y posteriormente accederemos a la base de datos a partir del nombre del perfil.

En el perfil DSN lo que se hace es indicar el driver a utilizar, así como el archivo o archivos del origen de datos. Estos son los pasos a llevar a cabo para configurar un perfil DSN.

1.- Iremos a Panel de Control. Ello se hace desde Inicio->Configuración o desde MiPC.

2.- Ahora hacemos doble-click en el icono de Fuentes de datos ODBC (32 bits).
3.- En nuestra pantalla aparecerá ahora la pestaña DSN usuario seleccionada. Para crear un nuevo perfil haremos click en Agregar...
4.- A continuación se nos pide que ingresemos el controlador que vamos a usar en el nuevo perfil. En nuestro caso será Microsoft Access Driver (*.mdb).
5.- Una vez aquí sólo nos queda dar un nombre al origen de datos y especificar el archivo .mdb de origen. Tras aceptar la ventana ya tenemos creado un perfil con lo que ya podemos comenzar a programar.

Clases, objetos y métodos básicos

Lo que necesitamos para hacer nuestro programa es la API JDBC incluida en la última versión del JDK. El paquete a utilizar y el cual deberemos importar es el paquete java.sql
Las primeras líneas de código suelen ser rutinarias ya que siempre serán muy similares.


Cargar el Driver

Lo primero es hacer una llamada al Driver JDBC-ODBC para cargarlo. Eso se consigue con las siguientes líneas de código:

try{Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); }
catch(Exception e){ System.out.println("No se ha podido cargar el Driver JDBC-ODBC"); }

Con esto ya tenemos cargado el Driver. Ahora básicamente trabajaremos con tres objetos. Estos objetos son: Connection, Statement y ResultSet. El objeto Connection se obtiene al realizar la conexión a la base de datos. El objeto Statement se crea a partir del anterior y nos permite ejecutar SQL para hacer consultas o modificaciones en la base de datos. En caso de hacer una consulta (SELECT ... FROM ...) se nos devolverá un objeto que representa los datos que deseamos consultar; este objeto es un objeto ResultSet (Hoja de resultados).

El objeto Connection

Debemos realizar la conexión a nuestro origen de datos. Para ello debemos crear un objeto Connection de la siguiente forma:
Connection con = DriverManager.getConnection("jdbc:odbc:Nombre_Perfil_DSN", "Nombre_Usuario", "Contraseña");


Los dos últimos parámetros pueden ser cadenas vacías "" a no ser que la base de datos las requiera. Con esto ya hemos realizado una conexión a nuestra base de datos. Pero esto todavía no es suficiente. Ahora vamos a crear un objeto Statement con el que podremos ejecutar y hacer consultas SQL. Si hasta ahora todo ha sido rutinario a partir de ahora vamos a poder crear código más adaptado a las necesidades de nuestro programa.

El objeto Statement

Como se ha dicho, un objeto Statement se crea a partir del objeto Connection antes obtenido. También como se ha dicho un objeto Statement nos permite hacer consultas SQL que nos devuelven una hoja de resultados. Pues bien, según como deseamos que sea esa hoja de resultados (modificable, o no, sensible a las modificaciones o no,...) deberemos crear de una forma u otra el objeto Statement. Más adelante se explican las diferencias entre crearlos de una u otra forma. De momento nos limitaremos ha hacerlo de la forma más sencilla.
Statement stat = con.createStatement();


De esta forma muy simple hemos creado un objeto Statement. Ahora podemos usar este objeto Statement para hacer modificaciones en la base de datos a través del lenguaje SQL. Para realizar modificaciones, es decir, instrucciones INSERT, UPDATE o DELETE, se usa el método executeUpdate pasando como parámetro una cadena de texto String que contenga la instrucción SQL.

Para hacer una consulta, es decir, una instrucción SELECT debemos usar otro método: el método executeQuery que como el anterior se le ha de pasar un String que contenga la instrucción. Este método nos devuelve un objeto ResultSet que contiene los datos obtenidos. Este objeto será diferente según como hayamos creado el objeto Statement. En el ejemplo anterior hemos usado un método muy simple de Connection para crear el objeto Statement, pero hay otras formas de crearlo. Estas son y estas son las características que aportan a la hoja de resultados de una consulta:

El método anteriormente utilizado es el siguiente: createStatement(), pero existe el mismo método al que le podemos pasar dos parámetros. En la documentación se expresa así: createStatement(int resultSetType, int resultSetConcurrency).
Los posibles valores a pasar son campos de la clase ResultSet. Por ejemplo para el parámetro resultSetType podemos elegir que el objeto ResultSet se pueda mover (entre registros) sólo hacia delante (ResultSet.TYPE_FORWARD_ONLY), que se pueda mover pero que cuando se actualice, aunque los cambios ya hayan sido reflejados en la base de datos, el ResultSet no los 'sienta' (ResultSet.TYPE_SCROLL_INSENSITIVE) o que se pueda mover y que los cambios si que se reflejen también en él (ResultSet.TYPE_SCROLL_SENSITIVE). Para el parámetro resultSetConcurrency podemos establecer dos valores diferentes:

ResultSet.CONCUR_READ_ONLY si queremos que los datos se puedan leer pero no actualizar, y ResultSet.CONCUR_UPDATABLE si queremos permitir que la base de datos sea actualizable mediante el objeto ResultSet. Si no se usa el método sin parámetros el objeto será TYPE_FORWARD_ONLY y CONCUR_READ_ONLY.

El objeto ResultSet: Hoja de resultados

Moverse por la hoja de resultados

Al hablar de posición del cursor nos referimos a la posición dentro de los datos del objeto ResultSet. Lo primero que hay que saber es que el cursor tiene tantas posiciones como filas tenga la consulta y dos más que se sitúan antes de la primera fila y después de la última. Nada más crear un objeto ResultSet, la posición del cursor es la anterior a la primera fila.

Para mover el cursor a la posición siguiente usaremos el método next() que nos devuelve una variable booleana: sí, si se ha podido mover; no, si no ha sido posible el desplazamiento. Nos devolverá false si estamos en el último registro (el posterior al último). Para movernos hacia atrás tenemos un método muy similar: el método previous() que al igual que el anterior nos devuelve un valor booleano que será false si estamos en el registro anterior al primero. Estos métodos nos permiten movernos de forma relativa por la hoja de resultados; si deseamos movernos a un registro determinado usaremos el método absolute(int numero_fila), que también nos devuelve un valor boolean. Además tenemos otros métodos que son: afterLast(), que mueve el cursor a la fila posterior a la última; beforeFirst() que mueve el cursor a la fila anterior a la primera; last() que mueve el cursor a la última fila; first() que mueve el cursor a la primera fila. Todos ellos devuelven un valor booleano.

Obtener datos de la hoja de resultados

Para acceder a los datos de la hoja de resultados usamos los métodos get...(int numeroColumna) o get...(String nombreColumna). Estos métodos nos devuelven el valor que indica el nombre del método (por ejemplo tenemos: getString, getInt, getDate, ...) indicando el número o el nombre de la columna. Hay que tener en cuenta que el número de columna es el número de columna en la hoja de resultados y por tanto se establece con el orden en el que se han incluido las columnas en la instrucción SELECT. Por ejemplo si hemos hecho la consulta de la siguiente forma: SELECT Nombre, Apellidos ... la columna Nombre será la primera y la columna Apellidos será la segunda independientemente de cómo estén situadas en la base de datos. Si hacemos un SELECT * FROM ..., en ese caso las columnas estarán en el orden en el que están en la base de datos.

Modificar la base de datos con el objeto ResultSet

Hemos dicho que mediante el objeto Statement podemos ejecutar sentencias SQL para modificar la base de datos y hacer consultas, por lo que podemos usar el lenguaje SQL para hacer cualquier operación en la base de datos; pero además tenemos métodos especializados que nos permiten hacer estas mismas tareas sin usar el lenguaje SQL. Para ello se usan los métodos especializados del objeto ResultSet. Por tanto si deseamos modificar la base de datos a través de Java, sin utilizar SQL, lo primero que deberemos hacer es realizar una consulta SQL para obtener el objeto ResultSet (parece un poco paradógico). Ahora sólo nos queda usar los métodos especializados de este objeto.

Por ejemplo podemos usar deleteRow() para borrar una fila.
Para actualizar una fila se usan los métodos update...(NombreColumna, valor) o update...(NumeroColumna, valor), así podemos encontrar updateFloat, updateString, ... Para que los cambios se reflejen en la base de datos se debe llamar al método updateRow() o cancelRowUpdates() si queremos cancelar la actualización.
resultset.updateString("Nombre", "PEPE");resultset.updateRow();
Para insertar una fila nos hemos de mover a un lugar del cursor especial con el método toInsertRow(), una vez allí usaremos los métodos update... explicados antes y para reflejar esta actualización llamar al método insertRow().[1]


2. CONECTAR BD ORACLE CON JAVA

Para poder conectar a Java con ORACLE lo primero que necesitamos es la implementación de JDBC para ORACLE. Esta implementación se encuentra en el archivo Classes12.jar,
ORACLE_HOME es una variable de entorno que se crea durante la instalación del servidor ORACLE, y que indica donde está instalado fisicamente ORACLE dentro del sistema de archivos, normalmente C:\oracle\ora92 para servidores Windows y ORACLE 9i. Esta .misma nomenclatura se aplica al hablar de la instalación cliente
Debemos configurar correctamente nuestra variable CLASSPATH para incluir en ella el archivo Classes12.jar.


Oracle proporciona los siguientes drivers en su implementacion JDBC:
JDBC Thin Driver: No requiere de la instalación cliente de ORACLE. Ideal para Applets.
JDBC OCI :API nativa de ORACLE, para aplicaciones J2EE.
JDBC KPRB driver: (default connection) para Java Stored Procedures y Database JSP's.

Todos los drivers soportan la misma sintaxis y funcionalidad, por lo que nuestro código variará únicamente en la forma de crear la conexion.
Conectar a ORACLE con JDBC Thin Driver

El driver JDBC Thin se conecta y comunica con ORACLE a nivel de sockets. Proporciona su propia versión del protocolo Net8 (SQL*Net) sobre TCP/IP, por lo que no es necesario que exista una instalación de la parte cliente de ORACLE. Dado que este driver es código 100% Java es completamente independiente de la plataforma de ejecución, y como implementa su propia versión del protocolo es ideal para aplicaciones que se ejecutan sobre un navegador Web (applets)


import java.sql.*;
class dbAccess {
public static void main (String args []) throws SQLException
{
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@WIN01:1521:oracleBD", "user", "passw");
// driver@machineName:port:SID , userid, password
Statement stmt = conn.createStatement();
ResultSet rset =
stmt.executeQuery("select BANNER from SYS.V_$VERSION");
while (rset.next())
System.out.println (rset.getString(1));
// Print col 1 stmt.close(); } }

Conectar a ORACLE con JDBC OCI Driver

El driver JDBC OCI usa el API ORACLE OCI (Oracle Call Interface) para interactuar con ORACLE, por lo que es necesaria la instalación y configuración de la parte cliente de ORACLE. El driver OCI trabaja con SQL*Net o Net8, por lo que tamdebemos haber creado un alias en el archivo TNS names (%ORACLE_HOME%\network\ADMIN):

ORACLEBD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = WIN01)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = ORACLEBD)
)
)

El driver JDBC OCI permite realizar llamadas a ORACLE OCI directamente desde Java proporcionandoun alto grado de compatibilidad con una versión específica de ORACLE utilizando métodos nativos, pero específicos de la plataforma.

import java.sql.*;
class dbAccess
{
public static void main (String args []) throws SQLException
{
try
{
Class.forName ("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
Connection conn = DriverManager.getConnection
("jdbc:oracle:oci:@ORACLEBD", "user", "passw");
// @TNSNames_Entry, userid, password
Statement stmt = conn.createStatement();
ResultSet rset =
stmt.executeQuery("select BANNER from SYS.V_$VERSION");
while (rset.next())
System.out.println (rset.getString(1));// Print col 1
stmt.close();
}
}

Conectar a ORACLE con JDBC KPRB Driver

Por último el driver ORACLE JDBC KPRB es utilizado para escribir en Java procedimientos almacenados, funciones, triggers ... Ofrece acceso a la conexion activa por lo que no es necesario crear ninguna conexión adicional.

El driver JDBC KPRB de ORACLE permite obtener un handle de la conexion actual del contexto a través del método OracleDriver.defaultConenction(). Como hemos dicho, se utiliza para procedimientos almacenados, triggers .... Para ejecutar un procedimiento almacenado debemos estar conectados a ORACLE a través de una herramienta cliente como SQL*Plus., lo que hacemos con defaultConenction() es acceder a está conexion.

CREATE OR REPLACE AND COMPILE
JAVA SOURCE NAMED BANNER AS
import java.sql.*;
class dbAccess
{
public static String showBanner() throws SQLException
{ String banner="";
Connection conn =
(new oracle.jdbc.driver.OracleDriver()).defaultConnection();
Statement stmt = conn.createStatement();
ResultSet rset =
stmt.executeQuery("select BANNER from SYS.V_$VERSION");
while (rset.next())
banner += rset.getString(1);
//stmt.close(); NO CERRAR LA CONEXION
return banner;
}
}

Es necesario crear un "wrapper" para poder ejecutar el programa desde PL/SQL o SQL.

CREATE OR REPLACE FUNCTION ShowBanner RETURN VARCHAR2 IS
LANGUAGE JAVA NAME 'dbAccess.showBanner() return java.lang.String';

Una vez hecho esto, podemos ejecutar la función como si se tratase de una función PL/SQL.

SELECT ShowBanner FROM DUAL;
[2].


3. CONECTAR JAVA CON MYSQL

Para poder conectar java con una base de datos (MySQL en este ejemplo), necesitamos el Driver o Connector de la base de datos. Este Driver puede habitualmente bajarse de la página web de la base de datos.

En el zip que nos bajamos hay dentro un java-mysql-connector-5.0.5-bin.jar que es el que tiene dentro del Driver. Debemos poner este jar accesible a nuestro proyecto java:

Poniéndolo en $JAVA_HOME/lib/ext/ y así será accesible por defecto para siempre. Esta opción no es aconsejable, puesto que este jar estará disponible para todas las aplicaciones que corramos en el ordenador, lo necesiten o no. Si no somos cuidadosos, podemos tener conflictos entre distintas versiones o con otros jar que pongamos que ahí.

Poniéndolo en el CLASSPATH
Añadiéndolo a nuestro proyecto del IDE que usemos.
Una vez accesible, para conectarse a la base de datos hacemos esto

import java.sql.Connection;
import java.sql.DriverManager;
...
try
{
Class.forName("org.gjt.mm.mysql.Driver");
Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost/agenda", "root", "LA_PASSWORD"); ...
[3].


4. CONECTAR BD POSTGRES CON JAVA

import java.sql.*;
class Prueba {
public static void main (String args[])
{
// Comprobamos que nos han pasado el user y el password
if (args.length != 2) {
System.out.println("Error: prueba ");
System.exit(1);
}
// Cargamos el driver para postgresql
try {
Class.forName("org.postgresql.Driver"); }
catch (ClassNotFoundException e1) {
System.out.print("Prueba (cargando driver): ");
e1.getMessage(); e1.printStackTrace(); System.exit(1);
}
Connection db = DriverManager.getConnection ("jdbc:postgresql://localhost:5432/sdft", args[0], args[1]);
Statement st = db.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM prueba");
db.setAutoCommit(false);
Statement st = conn.createStatement(); st.setFetchSize(5); ResultSet rs = st.executeQuery("SELECT * FROM mytable")
// Consultamos los datos devueltos for (int i = 1; rs.next(); i++) { System.out.print("En la columna " + i + " tenemos un ");
System.out.println(rs.getInt(1)); }
// Cerramos la peticion y los datos rs.close(); st.close(); }
catch (Exception e) {
System.out.print("Prueba (accediento a la base de datos): "); e.getMessage(); e.printStackTrace(); System.exit(1);
}
}
}
[4].

* MANEJO DE EXCEPCIONES EN JAVA

El manejo de excepciones es una estructura de control de los lenguajes de programación diseñada para manejar condiciones anormales que pueden ser tratadas por el mismo programa que se desarrolla.

Por ejemplo, un programa puede admitir cierto número de errores en el formato de los datos y continuar su proceso para producir el mejor resultado posible en lugar de producir una salida aparatosa llena de mensajes de error probablemente incomprensibles para el usuario. Muchas veces la acción asociada a una excepción es simplemente producir un mensaje informativo y terminar, otras veces, es sólo indicación de la necesidad de un cambio en la estrategia de resolución del problema.

Ejemplo de manejo de excepción en Java:
import java.io.IOException;

// ...

public static void main(String[] args) {
try {
// Se ejecuta algo que puede producir una excepción
} catch (IOException e) {
// manejo de una excepción de entrada/salida
} catch (Exception e) {
// manejo de una excepción cualquiera
} finally {
// código a ejecutar haya o no excepción
}
}
[5].

A continuación se muestra cómo se utilizan las excepciones, reconvirtiendo en primer lugar el applet de saludo a partir de la versión iterativa de HolaIte.java:

import java.awt.*;
import java.applet.Applet;

public class HolaIte extends Applet {
private int i = 0;
private String Saludos[] = {
"Hola Mundo!",
"HOLA Mundo!",
"HOLA MUNDO!!"
};

public void paint( Graphics g ) {
g.drawString( Saludos[i],25,25 );
i++;
}
}

Normalmente, un programa termina con un mensaje de error cuando se lanza una excepción. Sin embargo, Java tiene mecanismos para excepciones que permiten ver qué excepción se ha producido e intentar recuperarse de ella.
Vamos a reescribir el método paint() de esa versión iterativa del saludo:

public void paint( Graphics g ) {
try {
g.drawString( Saludos[i],25,25 );
} catch( ArrayIndexOutOfBoundsException e ) {
g.drawString( "Saludos desbordado",25,25 );
} catch( Exception e ) {
// Cualquier otra excepción
System.out.println( e.toString() );
} finally {
System.out.println( "Esto se imprime siempre!" );
}
i++;
}

La palabra clave finally define un bloque de código que se quiere que sea ejecutado siempre, de acuerdo a si se capturó la excepción o no. En el ejemplo anterior, la salida en la consola, con i=4 sería:
C:\>java HolaIte
Saludos desbordado
¡Esto se imprime siempre!
[6].

* MANEJO DE JTABLE EN JAVA

Un JTable es un componente visual de java que nos permite dibujar una tabla, de forma que en cada fila/columna de la tabla podamos poner el dato que queramos; un nombre, un apellido, una edad, un número, etc, etc.
Como muchos componentes de java, se ha seguido una separación modelo-vista .
La vista es el componente visual que vemos en pantalla, el modelo es una clase que contiene los datos que luego se verán en pantalla. El modelo de datos únicamente contiene los datos, nosabe nada de quién va a visulizar los datos ni como.

La forma más rápida y sencilla

Aparte de usar otros constructores que hay en JTable, una de las mejores formas de manejar JTable teniendo toda su funcionalidad, consiste en instanciar como modelo de datos un DefaultTableModel y luego un JTable , pasándole el modelo en el constructor. El código quedaría:

DefaultTableModel modelo = new DefaultTableModel();J
Table tabla = new JTable (modelo);

A partir de ahora todo se maneja con el modelo. En cuanto añadamos, borremos o cambiemos datos del modelo, el JTable se enterará y actualizará automáticamente. El DefaultTableModel tiene todos los métodos necesarios para modificar datos en su interior, añadir filas o columnas y darle a cada columna el nombre que queramos

Vamos a hacer nuestro propio modelo de datos
El DefaultTableModel es un modelo genérico y puede no ser suficiente (o al menos, incómodo de usar) para nuestros propósitos.
Es bastante habitual el querer manejar la tabla como si fuera una lista, de forma que cada filacorresponde a una clase de datos y las columnas son los atributos de esaclase. Por ejemplo, queremos una lista de Persona y cada persona tiene unnombre, un apellido y una edad. Queremos pintar este lista en una tabla,de forma que tiene tres columnas (nombre, apellido y edad) y tantas filascomo Personas haya en la lista. A mi me gustaría tener un modelo alque le diga
modelo.anhadePersona (persona);

y no un
modelo.setValueAt (fila, columna, persona.nombre);columna++;modelo.setValueAt (fila, columna, persona.apellido);columna++;modelo.setValueAt (fila, columna, edad);
Por ello, a veces esmás cómodo implementar nuestros propios modelos de tabla. Lacosa es fácil, únicamente debemos implementar la interfaceTableModel y luego poner además todos losmétodos que queramos, como el anhadePersona() o el damePersona() mencionados antes.

Una clase que implemente un TableModel debe redefinir los siguientes métodos:
class MiModelo implements TableModel
{
public void addTableModelListener (TableModelListener l) {...}
public Class getColumnClass (int columIndex) {...}
public int getColumnCount() {...}
public String getColumnName (int columnIndex) {...}
public int getRowCount() {...}
public Object getValueAt (int rowIndex, int columnIndex) {...}
public boolean isCellEditable (int rowIndex, int columnIndex) {...}
public void removeTableModelListener (TableModelListener l) {...}
public void setValueAt (Object aValue, int rowIndex, int columnIndex)
}

Hay básicamente tres tipos de métodos:

Métodos para manejo de suscriptores al modelo. Un suscriptor es cualquier clase que quiera enterarse de cambios en los datos del modelo. El JTable es un ejemplo claro. El JTable se suscribe a cambios de datos en el modelo y de esta forma, en cuanto cambiemos datos en el modelo, el JTable se entera y se repinta automáticamente la pantalla. En este grupo están los métodos addTableModelListener() y removeTableModelListener()
Métodos para menejo de datos. Permiten obtener y cambiar datos dentro de la tabla. Son los métodos getValueAt() y setValueAt().

El resto son métodos para obtener información de la tabla en sí misma, como número de filas, número de columnas, si una fila-columna es o no editable, nombre de la columna, etc.

Métodos para los suscriptores

Para implementar los métodos de los suscriptores necesitamos que nuestro modelo tenga una lista de suscriptores y únicamente hay que añadir o borrar suscriptores de esa lista. El código puede ser tan simple como esto:

class MiModelo implements TableModel
{
public void addTableModelListener (TableModelListenerl) {
suscriptores.add (l);
}
public void removeTableModelListener (TableModelListener l) {
suscriptores.remove(l);<> }
private LinkedList suscriptores = new LinkedList();
}

Si en vez de implementar TableModel, heredamos de AbstractTableModel , ya tenemos esto implementado, además de otra serie de métodos que nos serán útiles más adelante.

Metodos para manejo de los datos

Para el manejode datos, sólo tenemos dos métodos. El que pone un dato enuna fila,columna y el que lo obtiene. Si seguimos con la idea de hacer unalista de personas, el código puede quedar como esto:

class MiModelo implements TableModel
{
public void setValueAt (Object dato, int fila, int columna) {
// Obtenemos la persona de la fila indicada
Persona aux = (Persona)datos.get (fila);
switch (columna) {
// Nos pasan el nombre.
case 0:
aux.nombre = (String)dato;
break;
// Nos pasan el apellido.
case 1:
aux.apellido = (String)dato;
break;
// Nos pasan la edad.
case 2:
aux.edad = ((Integer)dato).intValue();
break;
}
// Aquí hay que avisar a los sucriptores del cambio.
// Ver unpoco más abajo cómo.
}
public Object getValueAt (int fila, int columna) {
// Obtenemos la persona de la fila indicada
Persona aux = (Persona)datos.get (fila);
switch (columna) {
// Nos piden el nombre
case 0:
return aux.nombre;
break;
// Nos piden el apellido
case 1:
return aux.apellido;
break;
// Nos piden la edad.
case 2:
return new Integer (aux.edad);
break;
}
return null;
}
private LinkedList datos = new LinkedList();
}

Simplemente hemos declarado una lista de personas como atributo privado de la clase y hecho los switch necesarios para poner u obtener el campo concreto de Persona para la columna indicada. El Object recibido y devuelto para cada compo puede ser lo que nosotros queramos,pero para una fila,columna dada, debe ser del mismo tipo en ambos métodos. Dicho de otra forma, si devolvemos un Integer,nos pasarán un Integer. Además, debeser un Object (una instancia de una clase), por eso tratamos la edad como Integer y no como int.

El método setValueAt() tiene una pequeña pega. Cualquier modificación que hagamos en los datos, debe ser notificada a los suscriptores. Debemos crear un TableModelEvent , rellenarlo con los datos adecuados y avisar a los suscriptores.

El TableModelEvent se puede rellenar con el constructor. Parael caso de setValueAt() debemos ponerdespués de cambiar el dato (del switch) algo como esto

TableModelEvent evento = new TableModelEvent (this, fila, fila, columna);

Se le pasan como parámetros:

El modelo de datos que ha cambiado. En nuestro caso this.
La fila inicial que ha cambiado.
La fila final que ha cambiado, en nuestro caso la misma que la inicial, puesto que sólo ha cambiado una.
La columna que ha cambiado.
Una vez creado el evento, hay que pasárselo a los suscriptores a través de su método tableChanged()

int i;for (i=0; i
((TableModelListener)suscriptores.get(i)).tableChanged(evento);
Los demás métodos

Los demás métodos son de información general para la tabla y no tienen demasiado truco.

Devolver la clase de cada columna. Devolveremos String.class para el nombre y el apellido e Integer.class para la edad. Este método lo utiliza el JTable para saber como presentar o editar cada dato. Si el JTable no conoce la clase que le devolvemos (no es de las normales de java), lo más posible es que trate el dato como un Object yllame a su método toString() para pintarlo.

Devolver el número de columnas. Para nuestro ejemplo de Persona, que tiene tres campos, devolveremos un 3.

Devolver el nombre de las columnas. En nuestro ejemplo devolveremos "Nombre", "Apellido" y "Edad".

Devolver cuántas filas hay (el número de elementos en nuestra lista de personas)
Devolver si una celda en fila,columna es o no editable, es decir, si el usuario puede escribir en ella y modificar los datos del modelo. En nuestro ejemplo devolveremos true .

Otros métodos

Puesto que para eso hemos hecho este modelo, vamos a añadirle un par de métodos que nos son útiles para el ejemplo y nos facilitan el añadir y borrar personas:

public void anhadePersona (Persona nuevaPersona) {
// Añade la persona al modelo
datos.add (nuevaPersona);
// Avisa a los suscriptores creando un TableModelEvent...
TableModelEvent evento; evento = new TableModelEvent (
this, this.getRowCount()-1, this.getRowCount()-1, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT);
// ... y avisando a los suscriptores
int i;
for (i=0; i
((TableModelListener)suscriptores.get(i)).tableChanged(evento);
}[7].
TABLAS SIN COMPONENTES

Esta es una forma de crear tablas sencillas(sin componentes). Se indica primero el nombre de las columnas, en una cadena de parámetros, de la siguiente forma:

Las palabras que se encuentran en este tipo de letra son las cosas que el programador puede determinar y cambiar.
final String[] columnNames1 = {"HORA",
"LUNES",
"MARTES",
"MIÉRCOLES",
"JUEVES",
"VIERNES"};

Luego se indica el contenido que va a tener cada casilla, este entre paréntesis, teniendo en cuenta que el primer dato va a aparecer en la primera fila de la primera columna, el segundo dato va a aparecer en la primera fila de la segunda columna, y así sucesivamente, hasta acabar con todas las columnas de la primera fila, luego entre otro paréntesis, va a ir la información de todas las columnas de la segunda fila, y así hasta terminar con la cantidad de filas que se requieran:
final Object[][] info ={
{new Integer(720), "Química", "Modalidad", "Modalidad", "Modalidad", "Modalidad"},
{new Integer(850), "Ingles C.", "Filosofía", "Física", "Democracia", "L. Castellana"},
{new Integer(950), "DE", "S", "CA", "N", "SO"},
{new Integer(1020), "Filosofía", "Física", "Ingles C.", "L. Castellana",
"Calculo"},
{new Integer(1200), "DE", "S", "CA", "N", "SO"}, {new Integer(1230), "Filosofía", "Calculo", "Química", "Ed. Física",
"Talento"}
};

Se debe añadir esta información a la tabla, indicar el tamaño que esta va a tener, y añadir la tabla a un scrollpane; todo esto se realiza de la siguiente manera:
JTable table1 = new JTable(info, columnNames1);
table1.setPreferredScrollableViewportSize(new Dimension(500,100));
JScrollPane scrollPane1 = new JScrollPane(table1);

Además de la información, en el programa las tablas tienen colores de fondo y de letra, lo cual se realiza de la siguiente manera:
table1.setForeground(Color.blue);
table1.setBackground(Color.pink);
UTILIZANDO COMPONENTES

Para crear tabla con el TableModel, se crea una variable de tipo MyTableModel, para luego crear una nueva tabla, que contenga ese TableModel, de la siguiente manera:
MyTableModel myModel = new MyTableModel();
JTable table = new JTable(myModel);

Igualmente que en la anterior tabla, en esta es necesario decir el tamaño que va a tener nuestra tabla, y añadirla a un scrollpane
En esta tabla, solo se puede seleccionar una fila a la vez, además muestra en la terminal(desde donde se abrió el archivo), la fila y la columna seleccionada. Para poder realizar esto se debe utilizar el SelectionMode, primero se debe determinar si se puede seleccionar varias filas, y si se puede seleccionar varias columnas de la siguiente forma:
private boolean ALLOW_COLUMN_SELECTION = false;
private boolean ALLOW_COLUMN_SELECTION = true;

En esta tabla también se predeterminó el ancho de cada columna, para esto se utiliza el TableColumn, indicando la cantidad de columnas que se tienen y el tamaño de cada una; de la siguiente manera:
for (int i = 0, i <>
column =" table.getColumnModel().getColumn(i)
if(i == 1) {
column.setPregerredWidth(100); } else {
if(i== 2) {
column.setPreferredWidth(100); } else
if (i == 4){
column.setPreferredWidth(50); } else { column.setPreferredWidth(8); } } } }
Esta tabla utilizando UpIntegerEditor, y el programa WholeNumberFiel, permite identificar cuando en una casilla hay un número, y permitir únicamente el ingreso de números en el.

setUpIntegerEditor(table);
private void setUpIntegerEditor(JTable table) {
final WholeNumberField integerField = new WholeNumberField(0, 5);
integerField.setHorizontalAlignment(WholeNumberField.RIGHT);
DefaultCellEditor integerEditor = new DefaultCellEditor(integerField) {
public Object getCellEditorValue() {
return new Integer(integerField.getValue()); } };
table.setDefaultEditor(Integer.class, integerEditor); }

Para finalizar se crea una clase en la cual van los títulos de las columnas, y la información que va dentro de cada fila. Esta información se escribe igualmente que en la tabla anterior, solo que esta, como ya se había dicho anteriormente, va dentro de una nueva clase, la cual va de la siguiente forma:

class MyTableModel extends AbstractTableModel {
(Aquí van los nombres de las columnas y la información de cada fila)
public int getColumnCount() {
return columnNames.length; }
public int getRowCount() {
return informacion.length; ]
public String getColumnName(int col) {
return columnNames[col]; }
public Object getValueAt(int row, int col) {
return informacion[row][col]; }
public Class getColumnClass(int c) {
return getValueAt(0, c.getClass(); } [8].

* MANEJO DEJCOMBOBOX EN JAVA

Este componente ComboBox nos permite definir en primera instancia un conjunto de datos o valores respuestas asociados a una caja de edición cualesquiera, así ahora el usuario tendrá la oportunidad de seleccionar un dato del conjunto de datos o respuestas ya predefinido.
Este componente ComboBox tiene dos partes, una parte de encabezado, para poner el nombre del grupo de respuestas( por ejemplo municipios, sexo, etc.).

La segunda parte es la lista de opciones o respuestas que se debe cargar al tiempo de diseño de la ventana.

Al momento de ejecución del programa, toda la lista de respuestas, estarán a la vista del usuario, para que este ultimo la seleccione. [9].

Para utilizar la clase JComboBox en Java, hay que seguir una serie de pasos en los cuales se definirán variables y métodos de esta clase como se muestra en la siguiente figura:

Aquí el JComboBox, está mostrando una lista en la que se dan varias opciones predeterminadas del programa, y que para cada opción hay una acción al escogerla.
Para utilizar la clase JComboBox en un programa de Java, es necesario primero adicionar lo siguiente: String[] flechaStrings = {"imagen 1", "imagen 2", "imagen 3", "imagen 4", "imagen 5"};
Aquí primero se definen los valores que se van a tomar, en este caso los carros, para aceptar la variable de tipo String, y que va a ser util al momento de que se tomen estos valores en lista adicionandola a la clase JComboBox, ya veremos como.

En las siguientes instrucciones se darán pasos para el adicionamiento de variables a la clase JComboBox. public clase() { JComboBox lista = new JComboBox(flechaStrings); lista.setSelectedIndex(0);

Aquí estamos primero tomando la clase para que dentro de esa clase, defina una variable lista y la tome como como new JComboBox, y que además adquiera los valores de (flechaStrings); que ya habíamos definido anteriormente. [10].

Existen muchas ocasiones en donde el usuario del programa tiene que proporcionar datos que provienen de un conjunto finito y muy pequeño de posibles respuestas, esto significa que cada vez que se ejecute el programa, el usuario estará proporcionando las mismas respuestas.
Ejemplo de esta clase de datos, son por ejemplos Municipio en BC, las posibles respuestas solo son (Tecate, Tijuana, Mexicali, Ensenada, Rosarito), otro ejemplo es Sexo (Hombre, Mujer), etc.
Para situaciones como esta, existen componentes que permiten programar por adelantado las posibles respuestas, y el usuario solo debe seleccionar la respuesta apropiada , en lugar de tener que escribirla.

Recordar que el usuario al momento de ejecución del programa, solo vera el encabezado, para seleccionar su respuesta deberá apretar la flechita que esta a un lado del encabezado.
Ejemplo:

import java.lang.*; import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class prog16 {
//declaracion, creacion e inicializacion de componentes, objetos y variables
static JFrame ventana= new JFrame();
static JPanel p1= new JPanel(); static JPanel p2= new JPanel();
static String[] lista={"municipios","tecate","tijuana","ensenada","tecate"};
static JComboBox municipios = new JComboBox(lista );
static JTextField jt1=new JTextField(15); static JButton jb1= new JButton("OK");
// parte principal de programa
public static void main(String[] args)
{ // area de definicion de propiedades de el objeto
ventana.setTitle("mi programa");
ventana.setDefaultCloseOperation(ventana.EXIT_ON_CLOSE);
ventana.getContentPane().setLayout(new GridLayout(2,0));
//cargando panel1 con combobox y definiendo titulo
p1.setLayout(new GridLayout(1,0));
//observar que index cero es el titulo (aunque es un elemento mas)
municipios.setSelectedIndex(0); p1.add(municipios);
//cargando segundo panel con jbutton y jtextfield
p2.add(jb1); p2.add(jt1);
ventana.getContentPane().add(p1); ventana.getContentPane().add(p2);
ventana.pack(); ventana.setVisible(true);
jb1.addMouseListener( new MouseAdapter()
{ public void mousePressed(MouseEvent e){
// la propiedad getselecteditem() regresa un objeto
jt1.setText(String.valueOf( municipios.getSelectedItem() ) );
}} );
}; // termina main
} // termina clase
[9].

Listas y Cajas Combinadas

Las lista y cajas "combo" en Swing funcionan del mismo modo que lo hacían en el AWT, aunque tienen incrementada la funcionalidad a través de algunas funciones de conveniencia que se han incorporado. Por ejemplo, JList tiene un constructor al que se puede pasar un array de objetos String para que los presente. El ejemplo java1407.java, muestra el uso básico de estos dos componentes.
import java.awt.*;
import java.awt.event.*;
import com.sun.java.swing.*;

public class java1407 extends JPanel {

public java1407() {
setLayout( new GridLayout( 2,1 ) );

JList lista = new JList( java1406.ids );
add( new JScrollPane( lista ) );

JComboBox combo = new JComboBox();
for( int i=0; i < lista =" new" ventana =" new">
Una cosa que se ha mantenido con respecto a las listas de antes es que los objetos JList no proporcionan automáticamente la posibilidad de scroll o desplazamiento del contenido, que es una cosa que se espera que haga automáticamente, y resulta un poco chocante. No obstante, el añadir scroll a listas es sumamente sencillo, ya que es suficiente con incluir la JList en un JScrollPane, y todos los detalles del desplazamiento del contenido serán ya manejados bajo la responsabilidad del sistema.

Aunque lo más frecuente es que cada elemento seleccionable de una lista sea una etiqueta, Swing proporciona al componente JList también la posibilidad de presentar gráficos, con o sin texto asociado, y también proporciona un control adicional de eventos para adecuarse a los que se producen en la manipulación de este tipo de Componentes. Es decir, que en una lista también se pueden incluir instancias de clases como JButton, JTextField, JCheckBox, e incluso JTextArea, que es un componente multilínea.

Cada valor incluye el carácter de nueva línea, \n, para forzar el salto de línea en medio del texto.

class MiRendererDeLista extends JTextArea implements ListCellRenderer {
public Component getListCellRendererComponent(
JList lista,Object valor,int indice,
boolean seleccionado, boolean conFoco ) {

setBorder( new BevelBorder( BevelBorder.RAISED ) );
// Presenta el text correspondiente al item
setText( valor.toString() );
// Pinta en los colores indicados y con la fuente seleccionada...
if( seleccionado ) {
// .. en el caso de un item marcado (rojo/blanco)
setBackground( Color.red );
setForeground( Color.white );
}
else {
// .. en el caso de un item no marcado (gris/negro)
setBackground( Color.lightGray );
setForeground( Color.black );
}
return( this );
}
}

El código es bastante simple, y la parte más interesante es la correspondiente a la clase anidada MiRendererDeLista, reproducido antes, que implementa un controlador diferente para cada celda de la lista, extendiendo en este caso a JTextArea en lugar de JLabel, como suele ser habitual. El resultado de la ejecución del ejemplo es el que muestra la figura.
Aunque el componente JTextArea también tiene sus limitaciones, como son el no permitir el uso de gráficos, se puede observar que las posibilidades que se presentan al programador se han visto tremendamente incrementadas con la inclusión de este tipo de Componente y con las nuevas características que proporciona Swing. En este caso, incluso es posible hacer que la altura de la celda esté recortada, en el caso de utilizar fuentes de caracteres muy grandes, debido a que la altura de cada uno de los elementos seleccionables de la lista se determina en el momento en que son construidos. [11].
BIBLIOGRAFÌA

[1]. http://www.gamarod.com.ar/articulos/como_conectar_java_y_access.asp
[2]. http://www.devjoker.com/contenidos/Articulos/132/Como-conectar-a-ORACLE-con-Java.aspx
[3]. http://www.chuidiang.com/chuwiki/index.php?title=Conectar_java_con_mysql
[4]. http://deigote.blogspot.com/2006/06/servicios-web-4-instalando-postgresql.html
[5]. http://es.wikipedia.org/wiki/Manejo_de_excepciones
[6]. http://www.itapizaco.edu.mx/paginas/JavaTut/froufe/parte9/cap9-1.html
[7]. http://www.chuidiang.com/java/tablas/tablamodelo/tablamodelo.php
[8].http://www.gfc.edu.co/estudiantes/anuario/2003/sistemas/catalina/tercer_p/Tablas/c2.html
[9]. www.programacionfacil.com/java:jcombobox
[10].http://www.gfc.edu.co/estudiantes/anuario/2003/sistemas/orlando/SGML/Jcombobox/c22.html[11]. http://www.itapizaco.edu.mx/paginas/JavaTut/froufe/parte14/cap14-7.html
MARIA ISABEL FORERO FORERO
TEGNOLOGIA EN ANÀLISIS Y DESARROLLO DE SISTEMAS DE INFORMACIÒN
SERVICIO NACIONAL DE APRENDIZAJE "SENA"
CHIQUINQUIRÀ