Acesso simples e rápido às linhas de uma query

Abaixo segue duas classes para encapsular e facilitar o acesso a banco de dados via JDBC, a classe DBQuery encapsula uma query onde a mesma é capaz de gerar um iterator para navegação nas linhas da consulta de forma rápida, leve e eficiente.

O iterator é implementado de uma forma em que ele não guarde os dados da consulta em memória, possibilitando o uso dessa classe para queries que retornem muitas linhas de resultado.

Outra coisa interessante é a possibilidade de se trabalhar com genéricos, caso sua consulta ao banco retorne um tipo homogêneo de dados (por exemplo, todos os campos sejam do tipo String).

classe DBQuery.java

/**
 *
 * @author Paulo Canedo C Rodrigues
 */
public class DBQuery<t> implements Iterable</t><t> {
 
    private Connection connection;
    private String query;
 
    public DBQuery(Connection connection, String query) {
        this.connection = connection;
        this.query = query;
    }
 
    public Iterator</t><t> iterator() {
        try {
            Statement stm = connection.createStatement();
            ResultSet rs = stm.executeQuery(query);
            return new DBRowIterator(rs);
        } catch (SQLException ex) {
            return null;
        }
    }
}</t>

classe DBRowIterator.java

/**
 *
 * @author Paulo Canedo C Rodrigues
 */
public class DBRowIterator<t> implements Iterator<map <String, T>> {
 
    private ResultSet rs;
    private Map<string , T> rowFields = new HashMap</string><string , T>() {
 
        //Sobrescrita do metodo get do mapa para transformar o get em case insensitive
        @Override
        public T get(Object key) {
            return super.get(((String) key).toUpperCase());
        }
    };
    private String[] columnsName;
    private boolean objectReaded = false;
    private int columnCount;
 
    DBRowIterator(ResultSet rs) throws SQLException {
        this.rs = rs;
 
        columnCount = rs.getMetaData().getColumnCount();
        columnsName = new String[columnCount];
 
        for (int i = 0; i < columnCount; i++) {
            columnsName[i] = rs.getMetaData().getColumnName(i + 1).toUpperCase();
        }
    }
 
    public boolean hasNext() {
        if (objectReaded == false && rowFields.size() != 0) {
            return true;
        }
 
        try {
            boolean flag = rs.next();
            if (flag = true) {
                rowFields.clear();
                for (int i = 0; i < columnCount; i++) {
                    Object o = rs.getObject(i + 1);
                    rowFields.put(columnsName[i], (T) o);
                }
            } else {
                if (rowFields != null) {
                    try {
                        rs.getStatement().close();
                        rs.close();
                    } catch (Exception ex) {
                    }
                }
                rowFields = null;
            }
            return flag;
        } catch (Exception ex) {
        }
        return false;
    }
 
    public Map<String, T> next() {
        objectReaded = true;
        return rowFields;
    }
 
    public void remove() {
    }
}
</string></map></t>

Abaixo segue dois exemplos de utilização, por favor, deixem comentário sobre o que achou das classes e da ideia.

java.sql.Connection connection = null;
 
//Exemplo 1 com genérico sem casting - apenas para tipo de dados homogêneos
DBQuery dbQuery1 = new DBQuery(connection, "SELECT nome, sobrenome, endereco FROM tb_agenda ORDER BY nome");
for (Iterator<map <String, String>> it = dbQuery1.iterator(); it.hasNext();) {
    Map<string , String> linhaDaConsulta = it.next();
    String nome = linhaDaConsulta.get("nome"); //nome do campo da consulta: case insensitive
    String sobrenome = linhaDaConsulta.get("sobrenome");
    String endereco = linhaDaConsulta.get("endereco");
    System.out.println(String.format("Nome: %s; Sobrenome: %s; Endereço: %s", nome, sobrenome, endereco));
}
 
//Exemplo 2 sem genérico com casting
DBQuery dbQuery2 = new DBQuery(connection, "SELECT nome, idade, peso FROM tb_pessoa ORDER BY nome");
for (Iterator<map <String, Object>> it = dbQuery2.iterator(); it.hasNext();) {
    Map<string , Object> linhaDaConsulta = it.next();
    String nome = (String) linhaDaConsulta.get("nome");
    Integer idade = (Integer) linhaDaConsulta.get("idade");
    Float peso = (Float) linhaDaConsulta.get("peso");
    System.out.println(String.format("Nome: %s; Idade: %d; Peso: %.2f", nome, idade, peso));
}</string></map></string></map>