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
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /** * * @author Paulo Canedo C Rodrigues */ public class DBQuery<T> implements Iterable<T> { private Connection connection; private String query; public DBQuery(Connection connection, String query) { this.connection = connection; this.query = query; } public Iterator<T> iterator() { try { Statement stm = connection.createStatement(); ResultSet rs = stm.executeQuery(query); return new DBRowIterator(rs); } catch (SQLException ex) { return null; } } } |
classe DBRowIterator.java
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | /** * * @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, 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() { } } |
Abaixo segue dois exemplos de utilização, por favor, deixem comentário sobre o que achou das classes e da ideia.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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)); } |
Comentários