高效地从 H2 数据库中检索数据

Posted

技术标签:

【中文标题】高效地从 H2 数据库中检索数据【英文标题】:Retrieve data from H2 database efficiently 【发布时间】:2015-09-11 10:04:46 【问题描述】:

在我当前的项目中,我使用 H2 数据库来存储来自 JTable 的数据(准确地说是 TableModel 的数据)。

我已经编写了代码来保存表中的所有列,现在我想再次检索数据(从数据库加载)。

到目前为止一切顺利,但我想不出任何从数据库中检索数据并将其完善以再次添加到我的表中的好方法。 我有一种方法可以让我的表添加一个包含所有列数据的新行,所以这没问题(类似于public void addRow(Object dataForFirstCol, Object dataForSecondCol [...]),但我需要逐行获取数据。使用 H2 / Java SQL 怎么可能?

我发现ResultSet 会对此有所帮助,但我仍然需要通过 SQL 逐行获取数据,而 SELECT * FROM SOMEDATABASE 之类的内容不会有太大帮助。

非常感谢一些帮助让我开始,目前我 想不出比请求A列的所有数据,添加所有 必要的行到表中,并从上到下添加所有数据 该列(逐行)。然后为 B 列 请求数据并添加 将此逐行添加到表格B 列。对我来说,这通常似乎 是一个可能的解决方案,但添加一个完整的行会更令人满意 并且很可能对数千行具有更高的性能。

编辑:这是我用来创建和保存数据库的代码。不过,“DROP”查询仅用于测试目的。

/**
 * Save tables content into H2 database
 * @param filename of the database
 * @param table to get the contents from
 */
public void save(File filename, JTable table) 

    // prevent saving when user is editing a cell
    if (table.isEditing())  
        table.getCellEditor().stopCellEditing();
    

    try 
        Class.forName("org.h2.Driver");
        System.out.println(filename.toString());
        Connection conn = DriverManager.getConnection("jdbc:h2:" + filename.toString(), "sa", "");
        Statement state = conn.createStatement();

        state.execute("DROP TABLE IF EXISTS TASKS");

        state.execute("CREATE TABLE TASKS ("
                + "SeqNumber INT PRIMARY KEY,"
                + "FBNumber INT,"
                + "ReportNumber INT,"
                + "BetraNumber INT,"
                + "Date varchar(255),"
                + "StationName varchar(255)," 
                + "Kilometrage varchar(255),"
                + "BlockTime varchar(255),"
                + "WorkTime INT,"
                + "Worker varchar(255),"
                + "Task varchar(255),"
                + "Comments varchar(255),"
                + "ClosedState BOOLEAN," + ")"
                );

        String sqlInsert = "INSERT INTO TASKS " 

                + "(SeqNumber, "
                + "FBNumber, "
                + "ReportNumber, "
                + "BetraNumber, "
                + "Date, "
                + "StationName, "
                + "Kilometrage, "
                + "BlockTime, " 
                + "WorkTime, "
                + "Worker, "
                + "Task, "
                + "Comments, "
                + "ClosedState) "

        + "VALUES" 
        + "(?" // SeqNumber
        + ",?" // FBNumber
        + ",?" // ReportNumber
        + ",?" // BetraNumber
        + ",?" // Date
        + ",?" // StationName
        + ",?" // Kilometrage
        + ",?" // BlockTime
        + ",?" // WorkTime
        + ",?" // Worker
        + ",?" // Task
        + ",?" // Comments
        + ",?)"; // ClosedState

        for (int rowIndex = 0; rowIndex < table.getModel().getRowCount(); rowIndex++) 

            PreparedStatement sqlState = conn.prepareStatement(sqlInsert);

            sqlState.setInt(COLUMN_SEQ_NUMBER, getSeqNumber(table, rowIndex));
            sqlState.setInt(COLUMN_FB_NUMBER, getFBNumber(table, rowIndex));
            sqlState.setInt(COLUMN_REPORT_NUMBER, getRepNumber(table, rowIndex));
            sqlState.setInt(COLUMN_BETRA_NUMBER, getBetraNumber(table, rowIndex));

            sqlState.setString(COLUMN_DATE, getDate(table, rowIndex));
            sqlState.setString(COLUMN_STATION_NAME, getStationName(table, rowIndex));
            sqlState.setString(COLUMN_KILOMETRAGE, getKilometrage(table, rowIndex));
            sqlState.setString(COLUMN_BLOCK_TIME, getBlockTime(table, rowIndex));

            sqlState.setInt(COLUMN_WORK_TIME, getWorkTime(table, rowIndex));

            sqlState.setString(COLUMN_WORKER, getWorker(table, rowIndex));
            sqlState.setString(COLUMN_TASK, getTask(table, rowIndex));
            sqlState.setString(COLUMN_COMMENTS, getComments(table, rowIndex));
            sqlState.setBoolean(COLUMN_CLOSED_STATE, getClosedState(table, rowIndex));

            sqlState.executeUpdate();
        

        // This is also just temporary code to see the contents
        ResultSet dbContent = conn.createStatement().executeQuery("SELECT * FROM TASKS");
        while(dbContent.next()) 
            for (int i = 1; i+1 < DBDatabaseSystem.table.getColumnCount(); i++) 
                System.out.println(dbContent.getString(i));
            
        

        conn.close();
        unsavedChanges = false;

     catch (ClassNotFoundException e) 
        e.printStackTrace();
     catch (SQLException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
        DBDatabaseSystem.infoSystem.addError("Es gab ein SQL Problem beim Speichern der Datenbank");
     



【问题讨论】:

你为什么说SELECT * FROM SOMETABLE不会帮你?你的数据库表是怎么设计的? 哦,搞错了SELECT * FROM SOMEDATABASE 目前我所有的数据都存储在一个数据库一个表中。 网上可能有一些ResultSetTableModel源代码(搜索“resultset tablemodel”)。 如果你编辑你的问题并添加数据库表结构,JTable结构,你用来保存它的代码等会更有效率。现在一切都比较模糊。跨度> 【参考方案1】:

您向 Jtable 询问 retrive 并包含 save 的代码和简单的打印。

这里有一些理论想法:

显示来自数据库的 GUI 数据可能意味着很多行。 GUI(swing Jtable、SWT Table、web 等)在启动时显示在 100 行以下。我认为您应该将这些行放在开头。 接口public interface TableModel 检索惰性或 动态或分页(这样的词存在于网络中)实现,不幸的是官方支持/实现是未知的(对我来说)。谷歌显示了一些,不知道是好是坏。 几乎所有的执行都必须select count(*) from ... 执行getRowCount();然后使用norportable sql子句获取数据, 在 H2 中阅读此语法 select * ... LIMIT OFFSET 以获取具体行。我的问题不是很清楚,但您可能知道这个想法?

编辑:部分是关于垂直维度的(这个问题对我来说很难,我不是以英语为母语的人)。如果您考虑水平尺寸,通常我会从 ResulSet 行中获取一行的所有对象(列)到Map&lt;String,Object&gt;

【讨论】:

以上是关于高效地从 H2 数据库中检索数据的主要内容,如果未能解决你的问题,请参考以下文章

如何为第一个操作正确地从数组列表中检索数据

更高效地从 qtableWidget 更新和插入 MYSQL 数据库

尝试从 h2 数据库中检索 json 数据时出错

尝试使用 Quarkus 从本地 H2 数据库中检索所有行

如何高效地从多个表中查询子记录?

solr索引基本原理