usar una traer tabla registros mostrar llenar datos con como cargar java mysql swing jdbc jtable

traer - mostrar datos de una base de datos en java



Optimizar las llamadas de datos en JDBC en JTable (1)

actualmente tengo datos en el servidor MySQL y estoy llamando a los datos en JTable a través de JDBC. Sin embargo, hay 1369 filas y parece que tiene demasiados datos para cargar. Por lo general, demora 5 minutos en cargarse. ¿Hay alguna forma de optimizar el proceso? Este es mi código (me disculpo de antemano por un código desordenado):

public class DataTable { private String databaseName = "*****"; private String tableName = "******"; public void showDatabase(){ Connection conn = null; DatabaseMetaData meta = null; Statement stmt = null; ResultSet rs = null; int k = 0; try{ Class.forName("com.mysql.jdbc.Driver").newInstance(); String connectionUrl = "jdbc:mysql://localhost:3306/" + databaseName; String connectionUser = "*****"; String connectionPassword = "*****"; conn = DriverManager.getConnection(connectionUrl, connectionUser, connectionPassword); stmt = conn.createStatement(); meta = conn.getMetaData(); dataSets(stmt, meta); }catch(Exception e){ e.printStackTrace(); } finally{ try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (stmt != null) stmt.close(); } catch (SQLException e) { e.printStackTrace(); } try { if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } //return the column size of the table public int getColumnNumber(DatabaseMetaData meta, Statement stmt) throws SQLException { //ResultSet rs = meta.getColumns(null, null, "practiceexample", null); ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName); ResultSetMetaData rsmd = rs.getMetaData(); int columnsNumber = rsmd.getColumnCount(); return columnsNumber; } //return the rowNumber of the tables public int getRowNumber(Statement stmt) throws SQLException { ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName); int rowCount = 0; while(rs.next()){ rowCount = rs.getInt(1); } return rowCount; } public void dataSets(Statement stmt, DatabaseMetaData meta) throws SQLException { String[] columnNames = new String[getColumnNumber(meta, stmt)]; String[][] dataSets = new String[getRowNumber(stmt)][columnNames.length]; ResultSet column = meta.getColumns(null, null, tableName, null); int i = 0; while(column.next()) { columnNames[i] = column.getString("COLUMN_NAME"); //columnNames.add(i, column.getString("COLUMN_NAME")); i++; } for(int j = 0; j < dataSets.length; j++) { String[] singleRowData = new String[columnNames.length]; ResultSet data = null; for(int k = 0; k < columnNames.length; k++) { String columnName = columnNames[k]; data = stmt.executeQuery("SELECT " + columnName + " FROM " + tableName + " LIMIT " + j + ", " + 1); while(data.next()) { singleRowData[k] = data.getString(columnName); } } dataSets[j] = singleRowData; } SimpleTable table = new SimpleTable(columnNames, dataSets); javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { table.createAndShowGUI(); } }); } class SimpleTable{ String[] columns; String[][] dataSets; public SimpleTable(String[] columns, String[][] dataSets){ this.columns = columns; this.dataSets = dataSets; } public void createAndShowGUI(){ JPanel gui = new JPanel(new BorderLayout(3, 3)); final JTable table = new JTable(new DefaultTableModel(dataSets, columns)); final JScrollPane scrollPane = new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED , JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); Dimension dimension = table.getPreferredSize(); scrollPane.setPreferredSize(new Dimension(dimension.width, table.getRowHeight() * 30)); JPanel navigation = new JPanel(new FlowLayout(FlowLayout.CENTER)); JButton next = new JButton(">"); next.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { int height = table.getRowHeight() * (20-1); JScrollBar bar = scrollPane.getVerticalScrollBar(); bar.setValue(bar.getValue() + height); } }); JButton previous = new JButton("<"); previous.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent ae) { int height = table.getRowHeight()*(20-1); JScrollBar bar = scrollPane.getVerticalScrollBar(); bar.setValue( bar.getValue()-height ); } } ); navigation.add(previous); navigation.add(next); gui.add(scrollPane, BorderLayout.CENTER); gui.add(navigation, BorderLayout.SOUTH); JOptionPane.showMessageDialog(null, gui); } } }


En mi humilde opinión, la raíz de la mala reputación es que consulta innecesariamente la base de datos varias veces 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 (esto es lo 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 ResultSetMetaData asociado deberían ser suficientes para lograr su objetivo. Adicionalmente, 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();