当前位置: 首页 > 面试题库 >

优化在JDBC上调用JTable的数据

詹亮
2023-03-14
问题内容

目前,我在MySQL服务器中有数据,并且正在通过JDBC将数据调用到JTable上。但是,共有1369行,并且似乎有太多数据无法加载。加载通常需要5分钟。无论如何,有没有优化流程?这是我的代码(我事先为一个混乱的代码道歉):

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);
    }
}


}

问题答案:

恕我直言,坏习惯的根源是您不必要地查询数据库的多重时间来获取所需的数据(列,行,行号,列号等):

要获取列号:

ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName);

要获取行号:

ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);

要获取行(这是最糟糕的原因,因为它在循环内):

data = stmt.executeQuery("SELECT " + columnName + " FROM " + tableName + " LIMIT " + j + ", " + 1);

如何解决

只需查询数据库一次。单个ResultSet及其关联的ResultSetMetaData应该足以实现您的目标。另外,正如已经建议的那样,使用a
SwingWorker在单独的线程中进行数据库调用。例如:

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();


 类似资料:
  • 我正在使用YouTube数据应用编程接口为我最喜欢的一些频道获取视频列表。在功能上,一切都很好,但是现在我感兴趣的频道列表已经增加了,我达到了每日配额。 我目前是这样做的(伪代码): 这很好;我为每个频道获取最近的10个视频。 我想我想做的是: 对于每个频道,请确定最后一个视频的日期 对于在过去“n”天内有最近视频的每个频道,请获取最近的10个视频(根据上面的代码) 我在API上看不到任何用于查找

  • 我有一个mongoDB集合,我正在使用java驱动程序从mongo集合中获取数据。 我有一个电话号码列表,我需要在mongoDB集合中搜索所有这些手机号码。 假设我有500个手机号码,目前从我的java代码来看,我会说: 现在的问题是我打了500次DB。。 我想知道是否有更好的方法来处理,例如在RDBMS中,我们如下所示 所以像上面的查询一样,单次调用就足够了,但是在in子句中传递给SQL的参数数

  • 问题内容: 从Java 8开始,Java不提供尾叫优化(TCO)。经过研究,我知道原因是: 在JDK类中,有许多对安全性敏感的方法,它们依赖于对JDK库代码和调用代码之间的堆栈帧进行计数,以确定谁在调用它们。 但是,基于JVM的Scala支持尾叫优化。Scala在编译时进行尾递归优化。Java为什么不能使用相同的方法? PS:不确定Java的最新版本(截至现在的Java 11)是否具有TCO。如果

  • 我需要使用JDBC在Oracle数据库中进行大量插入,即两位数百万。为此,我使用了类似于以下类的东西,灵感来自使用JDBC进行批处理插入的高效方法: 虽然这种插入方式很好,但速度非常慢。JDBC batch insert performance描述了MySQL基本上可以解决这个问题,因为在Oracle上似乎不存在,但在这里没有太大帮助。 为了提高性能,我还尝试将语句切换为一个大的

  • 问题内容: 嗨,我已经成功地将jTable链接到JDBC数据库。但是,我在检索它们时遇到了麻烦。我希望在重新启动程序时出现保存的数据,但是它不起作用。 这是我保存文档的代码! 有什么方法可以检索JDBC数据库中的数据并通过Jtable显示它?我很抱歉提出这样一个简单的问题,但是我是Java新手,我非常需要帮助! 非常感谢! 用于加载数据的代码… 顺便说一句,我的jtable是一个3列的表,其中包含

  • 尾部调用优化对返回void的函数的递归调用有效吗?例如,我有一个函数,void fun() 在这里,编译器不会知道,调用fun()是最后一条语句。那么尾部调用优化是否只针对返回某些值的函数?