返回结果集

2022-09-01 16:20:22

我正在尝试创建一个方法,从中可以查询数据库并检索整个表。

目前,如果我使用方法中的数据,它工作得很好。但是,我希望该方法返回结果。

我正在获取当前代码。java.sql.SQLException: Operation not allowed after ResultSet closed

我怎样才能做到这一点?

public ResultSet select() {

    con = null;
    st = null;
    rs = null;

    try {
        con = DriverManager.getConnection(url, user, password);
        st = con.createStatement();

        rs = st.executeQuery("SELECT * FROM biler");
        /*
        if (rs.next()) {
            System.out.println(rs.getString("model"));
        }*/

    } catch (SQLException ex) {
        Logger lgr = Logger.getLogger(MySQL.class.getName());
        lgr.log(Level.SEVERE, ex.getMessage(), ex);

    } finally {
        try {
            if (rs != null) {
                rs.close();
            }
            if (st != null) {
                st.close();
            }
            if (con != null) {
                con.close();
            }

        } catch (SQLException ex) {
            Logger lgr = Logger.getLogger(MySQL.class.getName());
            lgr.log(Level.WARNING, ex.getMessage(), ex);
        }
    }

    return rs;
}

答案 1

你永远不应该通过公共方法传递一个。这很容易导致资源泄漏,因为您被迫保持语句和连接处于打开状态。关闭它们将隐式关闭结果集。但是,保持它们打开会导致它们晃来晃去,并在打开太多资源时导致数据库耗尽资源。ResultSet

像这样将其映射到Javabeans的集合,然后返回它:

public List<Biler> list() throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    List<Biler> bilers = new ArrayList<Biler>();

    try {
        connection = database.getConnection();
        statement = connection.prepareStatement("SELECT id, name, value FROM Biler");
        resultSet = statement.executeQuery();

        while (resultSet.next()) {
            Biler biler = new Biler();
            biler.setId(resultSet.getLong("id"));
            biler.setName(resultSet.getString("name"));
            biler.setValue(resultSet.getInt("value"));
            bilers.add(biler);
        }
    } finally {
        if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
        if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
        if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
    }

    return bilers;
}

或者,如果您已经在Java 7上,只需使用try-with-resources语句,它将自动关闭这些资源:

public List<Biler> list() throws SQLException {
    List<Biler> bilers = new ArrayList<Biler>();

    try (
        Connection connection = database.getConnection();
        PreparedStatement statement = connection.prepareStatement("SELECT id, name, value FROM Biler");
        ResultSet resultSet = statement.executeQuery();
    ) {
        while (resultSet.next()) {
            Biler biler = new Biler();
            biler.setId(resultSet.getLong("id"));
            biler.setName(resultSet.getString("name"));
            biler.setValue(resultSet.getInt("value"));
            bilers.add(biler);
        }
    }

    return bilers;
}

顺便说一句,你根本不应该声明 ,并且作为实例变量(主要的线程安全问题!),也不应该在这一点上吞咽 (调用方不会知道发生了问题),也不应该关闭相同的资源(例如,如果结果集 close 抛出异常,那么语句和连接仍然处于打开状态)。所有这些问题都已在上面的代码片段中修复。ConnectionStatementResultSetSQLExceptiontry


答案 2

如果您不知道检索时间的ResultSet是什么,我建议您将完整的东西映射到如下所示的映射中:

    List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
    Map<String, Object> row = null;

    ResultSetMetaData metaData = rs.getMetaData();
    Integer columnCount = metaData.getColumnCount();

    while (rs.next()) {
        row = new HashMap<String, Object>();
        for (int i = 1; i <= columnCount; i++) {
            row.put(metaData.getColumnName(i), rs.getObject(i));
        }
        resultList.add(row);
    }

所以基本上你有和ResultSet相同的东西(没有ResultSetMetaData)。


推荐