由 ResultSet 支持的 Java 迭代器

2022-09-01 06:19:36

我有一个类,它实现了迭代器,并将结果集作为数据成员。从本质上讲,该类如下所示:

public class A implements Iterator{
    private ResultSet entities;
    ...
    public Object next(){
        entities.next();
        return new Entity(entities.getString...etc....)
    }

    public boolean hasNext(){
        //what to do?
    }
    ...
}

如何检查结果集是否具有另一行,以便我可以创建有效的 hasNext 方法,因为结果集没有 hasNext 定义自身?我正在考虑进行查询以获取计数并管理该数字以查看是否有另一行,但我想避免这种情况。SELECT COUNT(*) FROM...


答案 1

这是个坏主意。这种方法要求连接一直处于打开状态,直到读取最后一行,并且在DAO层之外,您永远不知道它何时会发生,并且您似乎还会使结果集保持打开状态,并在连接超时的情况下面临资源泄漏和应用程序崩溃的风险。你不想拥有它。

正常的 JDBC 做法是在尽可能的范围内获取 。正常的做法是,您将多行映射到一个或一个,然后猜猜看,它们确实有一个.ConnectionStatementResultSetListMapIterator

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

    try (
        Connection connection = database.getConnection();
        Statement statement = connection.createStatement("SELECT id, name, value FROM data");
        ResultSet resultSet = statement.executeQuery();
    ) {
        while (resultSet.next()) {
            list.add(map(resultSet));
        }
    }

    return list;
}

private Data map(ResultSet resultSet) throws SQLException {
    Data data = new Data(); 
    data.setId(resultSet.getLong("id"));
    data.setName(resultSet.getString("name"));
    data.setValue(resultSet.getInteger("value"));
    return data;
}

并按如下方式使用它:

List<Data> list = dataDAO.list(); 
int count = list.size(); // Easy as that.
Iterator<Data> iterator = list.iterator(); // There is your Iterator.

不要像您最初想要的那样将昂贵的数据库资源传递到 DAO 层之外。有关正常 JDBC 实践和 DAO 模式的更多基本示例,您可能会发现本文很有用。


答案 2

您可以通过在 中执行前瞻并记住您进行了查找以防止消耗太多记录来摆脱这种泡菜,如下所示:hasNext()

public class A implements Iterator{
    private ResultSet entities;
    private boolean didNext = false;
    private boolean hasNext = false;
    ...
    public Object next(){
        if (!didNext) {
            entities.next();
        }
        didNext = false;
        return new Entity(entities.getString...etc....)
    }

    public boolean hasNext(){
        if (!didNext) {
            hasNext = entities.next();
            didNext = true;
        }
        return hasNext;
    }
    ...
}