由ResultSet支持的Java迭代器


问题内容

我有一个用ResultSet作为数据成员实现Iterator的类。本质上,该类如下所示:

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?
    }
    ...
}

我如何检查ResultSet是否有另一行,所以由于ResultSet本身未定义hasNext,因此可以创建有效的hasNext方法?我当时在想SELECT COUNT(*) FROM...查询以获取计数并管理该数字以查看是否还有另一行,但我想避免这种情况。


问题答案:

这是一个坏主意。这种方法要求连接一直保持打开状态,直到读取最后一行为止,并且在DAO层之外,您永远都不知道何时会发生连接,并且您似乎也保持结果集处于打开状态,并且在这种情况下可能会导致资源泄漏和应用程序崩溃连接超时。你不想那样。

正常JDBC的做法是,你购买ConnectionStatementResultSet最短的
可能范围。通常的做法是,将多行映射到a List或a中,Map然后猜测它们 确实 有一个Iterator

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模式的更多基本示例,您可能会发现本文很有用。