En mi humilde opinión, la raíz del mal rendimiento es que consulta la base de datos varias veces innecesariamente para obtener los datos (columnas, filas, número de filas, número de columnas, etc.) que necesita:
Para obtener el número de columnas:
ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName);
Para obtener el número de filas:
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);
Para obtener filas (este es el peor porque está dentro de un bucle):
data = stmt.executeQuery("SELECT " + columnName + " FROM " + tableName + " LIMIT " + j + ", " + 1);
Cómo resolverlo
Solo consulta la base de datos una vez. Un único ResultSet
y su asociado ResultSetMetaData
debería ser suficiente para lograr su objetivo. Además, y como ya se sugirió, use un SwingWorker
para hacer llamadas a la base de datos en un hilo separado. Por ejemplo:
final JTable table = new JTable();
SwingWorker<Void, TableModel> worker = new SwingWorker<Void, TableModel> () {
@Override
protected Void doInBackground() throws Exception {
ResultSet resultSet = stmt.executeQuery("SELECT * FROM " + tableName);
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount(); // columns number
String[] columnNames = new String[columnCount];
for (int i = 1; i <= columnCount; i++) {
columnNames[i] = metaData.getColumnName(i); // fill columns names
}
resultSet.last();
int rowCount = resultSet.getRow(); // get rows number
resultSet.beforeFirst();
Object[][] data = new Object[rowCount][columnCount];
int currentRow = 0;
while (resultSet.next()) {
for (int currentColumn = 1; currentColumn <= columnCount; currentColumn++) {
data[currentRow][currentColumn - 1] = resultSet.getObject(currentColumn); // fill data set
}
currentRow++;
}
TableModel model = new DefaultTableModel(data, columnNames);
publish(model);
return null;
}
@Override
protected void process(List<TableModel> chunks) {
TableModel model = chunks.get(0);
table.setModel(model);
}
}
worker.execute();