Ejemplos java y C/linux

Tutoriales

Enlaces

Licencia

Creative Commons License
Esta obra está bajo una licencia de Creative Commons.
Para reconocer la autoría debes poner el enlace http://www.chuidiang.com

Meter un ResultSet en un JTable. El ResultSetMetaData

En este tutorial tenemos un ejemplo en el que se consulta una base de datos MySQL y el resultado se muestra en un JTable. Nos centraremos en cómo meter el ResultSet en el JTable y de paso crearemos una pequeña clase ConversorResultSetADefaultTableModel que se pueda usar siempre, independientemente de la consula, la tabla, el número de columnas, etc. Eso sí, con sus limitaciones. Haremos un uso simple de ResultSetMetaData para obtener la información necesaria para este código genérico.

LA BASE DE DATOS

Presuponemos que tenemos instalado MySQL y que hemos creado una base de datos y una tabla con datos similar a la siguiente:

mysql> create database prueba;
mysql> use prueba;
mysql> create table persona (id smallint auto_increment, nombre varchar(60), nacimiento date, primary key(id));
mysql> insert persona values (NULL, 'Pedro', '1995-09-12');

Es decir, una base de datos prueba con una tabla persona que tiene los campos id, nombre y nacimiento tal cual se ve en el recuadro.

También suponemos que tenemos disponible el jar con el Driver de MySQL y que lo ponemos en el CLASSPATH o lo añadimos a nuestro proyecto si usamos un IDE.

LA CONSULTA Y EL ResultSet

Primero se obtiene la conexión a la base de datos con un código como este:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost/prueba","usuario","clave");

Por supuesto tendrás que cambiar el "usuario" y "clave" por los que tú tengas en la base de datos. También, si la base de datos no corre en tu ordenador local, tienes que cambiar "localhost" por el nombre o IP del ordenador donde corra la base de datos.

El siguiente paso es realizar la consulta y obtener el ResultSet. El código es el siguiente

Statement s = conexion.createStatement();
ResultSet rs = s.executeQuery("select * from persona");

METER EL ResultSet EN UN JTable

Para meter los datos en el JTable, usaremos un DefaultTableModel. Para ello basta con instanciar el JTable de esta forma

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

Ahora sólo hay que rellenar el DefaultTableModel con los datos del ResultSet. La forma "manual" de hacer esto es la siguiente

// Creamos las columnas.
modelo.addColumn("id");
modelo.addColumn("nombre");
modelo.addColumn("nacimiento");

// Bucle para cada resultado en la consulta
while (rs.next())
{
   // Se crea un array que será una de las filas de la tabla.
   Object [] fila = new Object[3]; // Hay tres columnas en la tabla

   // Se rellena cada posición del array con una de las columnas de la tabla en base de datos.
   for (int i=0;i<3;i++)
      fila[i] = rs.getObject(i+1); // El primer indice en rs es el 1, no el cero, por eso se suma 1.

   // Se añade al modelo la fila completa.
   modelo.addRow(fila);
}

Con esto basta. Todo lo que hagamos en el DefaultTableModel se refresca automáticamente en el JTable. Por ello, según se va ejecutando este código, en el JTable se iran añadiendo automáticamente los datos.

LOS METADATOS

El código que acabamos de hacer está claro que es muy dependiente de la tabla de base de datos que estamos consultando. Hay que añadir tantas columnas como campos tenga el resultado de base de datos. El nombre de las columnas depende de qué estemos consultando, es decir, un nombre de persona, una marca de coche, etc.

Sin embargo, existe una forma más o menos automática de hacer esto. Dado un ResultSet que obtenemos como consulta de base de datos, podemos interrogarle sobre cuántas columnas tiene y cuáles son los nombres de sus campos. Con ello, podemos hacer el código anterior de forma genérica, de tal manera que sólo teniendo el ResultSet y le DefaultTableModelo, podemos rellenarlo sin saber en absoluto qué consulta ni qué tablas se han consultado.

Para obtener esta información, hay que pedirle los MetaDatos al ResulSet. El código que lo hace es este

ResultSetMetaData metaDatos = rs.getMetaData();

La clase ResultSetMetaData contiene toda la información sobre los campos de base de datos contenidos en el ResultSet. Necesitamos preguntarle por el número de columnas y por la etiqueta para cada una de las columnas. Este es el código que lo hace

// Se obtiene el número de columnas.
int numeroColumnas = metaDatos.getColumnCount();

// Se crea un array de etiquetas para rellenar
Object[] etiquetas = new Object[numeroColumnas];

// Se obtiene cada una de las etiquetas para cada columna
for (int i = 0; i < numeroColumnas; i++)
{
   // Nuevamente, para ResultSetMetaData la primera columna es la 1.
   etiquetas[i] = metaDatos.getColumnLabel(i + 1);
}

Listo. Ya hemos obtenido de forma genérica la información necesaria para rellenar el DefaultTableModel.

En la clase ConversorResultSetADefaultTableModel del ejemplo se hace precisamente esto. Se le pasa un DefaultTableModel y un ResultSet y se encarga de meter los datos de un lado a otro, utilizando este código genérico que hemos hecho. Una vez que tenemos el array de etiquetas, basta hacer esta llamada al DefaultTableModelo para configurar su número de columnas

modelo.setColumnIdentifiers(etiquetas);

El relleno de los datos es inmediato. Igual que el código "manual", pero se puede quitar el "3" y poner un "numeroColumnas".

EL EJEMPLO

En ResultSetATableModel.zip tienes los fuentes completos del ejemplo. Si tienes configurada la base de datos como se indicó al principio y tienes un usuario y password similar al del código, puedes desempaquetar, compilar y ejecutar con

Linux
$ unzip ResultSetATableModel.zip
$ export CLASSPATH=.:<path_driver_mysqql>/mysql-connector-java-3.1.12-bin.jar
$ javac chuidiang/ejemplos/base_datos/*.java
$ java chuidiang.ejemplos.base_datos.PruebaMySQL

Windows
$ unzip ResultSetATableModel.zip
$ set CLASSPATH=.;<path_driver_mysqql>\mysql-connector-java-3.1.12-bin.jar
$ javac chuidiang\ejemplos\base_datos\*.java
$ java chuidiang.ejemplos.base_datos.PruebaMySQL

Puesto que en el código de ejemplo he puesto que cada segundo se realice la consulta nuevamente y se refresquen los datos, mientras el progrma está en marcha puedes modificar, añadir o borrar datos de la tabla de base de datos. Verás como se actualizan en el JTable.

Puedes revisar los fuentes de ejemplo. La clase realmente interesante es ConversorResultSetADefaultTableModel que posiblemente puedas reutilzar tal cual o con pequeños cambios en tus proyectos.

Una pequeña observación respecto al código. Como SWING no es thread-safe, es decir, no se puede usar alegremente con varios hilos. Como en el ejemplo hay dos hilos: el del main y el de AWT, me he visto obligado en los sitios en que modifico el DefaultTableModel a usar un SwingUtilities.invokeAndWait(). Si quitas eso, es posible que te salten excepciones en el repintado del JTable (es lo que me pasaba a mí y por eso tuve que ponerlo).

Estadísticas y comentarios

Numero de visitas desde el 4 Feb 2007: