【问题标题】:Is Passing a result set in java possible?是否可以在 java 中传递结果集?
【发布时间】:2019-04-29 22:55:27
【问题描述】:

我正在尝试创建一个命令,我可以将不同的查询发送到 SQLite / Mysql DB,并将结果集返回给正在调用的任何函数。需要能够处理2列还是15列。

以下不起作用 - 大概是因为它关闭了结果集/连接,但我不知道该怎么做。

想法?

public static ResultSet queryDB(String query) {
    try {
        Connection connection = DriverManager.getConnection("jdbc:sqlite:" + Settings.SQLITE_DB_PATH);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(query);
        resultSet.close();
        statement.close();
        connection.close();
        return resultSet;
    } catch (SQLException ex) {
        Logger.getLogger(SQLInterp.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

【问题讨论】:

  • 你可以通过它,只要你不关闭它,或者它各自的Statement/Connection,然后再尝试读取它。
  • Jacob G - 这不会导致内存泄漏吗?
  • 假设你使用后关闭它,没有。
  • 关闭前返回结果怎么关闭?
  • @DotSlashShell 一种选择是不返回ResultSet,而是将Consumer<ResultSet> 作为参数传入ResultSet 本身。

标签: java sql sqlite


【解决方案1】:

你基本上有3个选择:

  1. 不要关闭方法中的ResultSetStatementConnection,将执行此操作的责任交给调用者。

    不推荐,因为它容易出错,并且会破坏格式良好的代码结构范例。

  2. 传入具有处理数据所需逻辑的对象,如suggested by Jacob G.

    例如使用 Java 8+ Consumer:

    public static void queryDB(String query, Consumer<ResultSet> processor) {
        try (
            Connection connection = DriverManager.getConnection("jdbc:sqlite:" + Settings.SQLITE_DB_PATH);
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(query);
        ) {
            processor.accept(resultSet);
        } catch (SQLException ex) {
            Logger.getLogger(SQLInterp.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    

    然后这样称呼它:

    SQLInterp.queryDB("SELECT * FROM foo", rs -> {
        while (rs.next()) {
            // process data here
        }
    });
    
  3. 以通用数据结构将所有数据读入内存,例如List&lt;Map&lt;String, Object&gt;&gt;:

    这当然假设查询对每一列都有很好的唯一名称。

    public static List<Map<String, Object>> queryDB2(String query) {
        try (
            Connection connection = DriverManager.getConnection("jdbc:sqlite:" + Settings.SQLITE_DB_PATH);
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(query);
        ) {
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            String[] name = new String[columnCount];
            for (int i = 0; i < columnCount; i++)
                name[i] = metaData.getColumnLabel(i + 1);
            List<Map<String, Object>> rows = new ArrayList<>();
            while (resultSet.next()) {
                Map<String, Object> row = new LinkedHashMap<>();
                for (int i = 0; i < columnCount; i++)
                    row.put(name[i], resultSet.getObject(i + 1));
                rows.add(row);
            }
            return rows;
        } catch (SQLException ex) {
            Logger.getLogger(SQLInterp.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    

【讨论】:

  • 非常感谢!我选择了#2,现在将尝试。但是连接如何关闭?
  • @DotSlashShell 代码使用try-with-resources,这是Java 7 中添加的一个功能。
  • 谢谢!有效。你能详细说明一下资源的尝试吗?我在 #2 中没有看到任何不同之处,即尝试使用资源或关闭连接?
  • @DotSlashShell 您是否按照我提供的链接进行操作,例如查看搜索列表中的The Java™ Tutorials - The try-with-resources Statement 文章?
猜你喜欢
  • 2022-11-21
  • 1970-01-01
  • 2021-06-24
  • 2022-09-27
  • 2017-03-15
  • 2023-03-09
  • 1970-01-01
  • 2018-07-01
  • 1970-01-01
相关资源
最近更新 更多