Este exemplo visa demonstrar como é simples implementar um TableModel para a JTable renderizar o ResultSet de uma consulta ao banco de dados.
Aplicação para exemplificar o uso
import java.awt.*;
import java.sql.*;
import javax.swing.*;
// pacote da classe ResultSetTableModel
import components.database.*;
public class Exemplo {
public static void main(String[] a) {
try {
String driver = "<classe do driver do banco>";
String url = "<url de acesso ao banco>";
String query = "<query a ser executada>";
Class.forName(driver).newInstance();
Connection conn = DriverManager.getConnection(url);
PreparedStatement ps = conn.prepareStatement(query);
ResultSet rs = ps.executeQuery();
JTable table = new JTable();
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// definir o modelo para a JTable renderizar o ResultSet
table.setModel(new ResultSetTableModel(rs));
JFrame frame = new JFrame("Teste ResultSetTableModel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.add(BorderLayout.CENTER, new JScrollPane(table));
frame.setVisible(true);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Implementação do TableModel
package components.database;
import java.sql.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* Implementação de um {@link TableModel} para renderizar o {@link ResultSet} de
* uma consulta ao banco
*
* @author Ricardo Artur Staroski
*/
public class ResultSetTableModel extends AbstractTableModel {
/**
* Classe interna utilizada para armazenar o nome de uma coluna e a classe
* Java correspondente ao tipo de dado da mesma
*/
private static class Column {
/**
* A classe Java do tipo de dado da coluna
*/
public final Class<?> CLASS;
/**
* O nome da coluna
*/
public final String NAME;
/**
* Instancia um objeto {@link Column} com o tipo de dado e nome
* informados
*
* @param type
* A classe Java correspondente ao tipo de dado da coluna
* @param name
* O nome da coluna
*/
public Column(final String name,
final Class<?> type) {
NAME = name;
CLASS = type;
}
}
/**
* Classe interna utilizada para armazenar os valores de um registro da
* tabela
*/
private static class Row {
/**
* Os valores de cada coluna do registro
*/
public final Object[] VALUES;
/**
* Instancia um objeto {@link Row} para o {@link ResultSet} informado
*
* @param rs
* O {@link ResultSet} da linha a ser processada
* @throws SQLException
*/
public Row(final ResultSet rs) throws SQLException {
final int columns = rs.getMetaData().getColumnCount();
VALUES = new Object[columns];
for (int i = 1; i <= columns; i++) {
VALUES[i - 1] = rs.getObject(i);
}
}
}
// Classes serializável, declarar este atributo para não gerar warnings
private static final long serialVersionUID = 1L;
// linsta de colunas da tabela
private List<Column> columns;
// lista de registros da tabela
private List<Row> lines;
/**
* Instancia um {@link ResultSetTableModel} para o {@link ResultSet}
* informado
*
* @param rs
* O {@link ResultSet} que a {@link JTable} deste modelo irá
* renderizar
* @throws SQLException
* @throws ClassNotFoundException
*/
public ResultSetTableModel(final ResultSet rs) throws SQLException,
ClassNotFoundException {
columns = new ArrayList<Column>();
final ResultSetMetaData md = rs.getMetaData();
final int count = md.getColumnCount();
for (int i = 1; i <= count; i++) {
columns.add(new Column(md.getColumnName(i),
Class.forName(md.getColumnClassName(i))));
}
lines = new ArrayList<Row>();
while (rs.next()) {
lines.add(new Row(rs));
}
}
@Override
public Class<?> getColumnClass(final int columnIndex) {
return columns.get(columnIndex).CLASS;
}
@Override
public int getColumnCount() {
return columns.size();
}
@Override
public String getColumnName(final int column) {
return columns.get(column).NAME;
}
@Override
public int getRowCount() {
return lines.size();
}
@Override
public Object getValueAt(final int rowIndex, final int columnIndex) {
return lines.get(rowIndex).VALUES[columnIndex];
}
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
return false;
}
}