Olá Pessoal, tudo bom?
Nessa semana iremos falar sobre a organização de um método de busca com filtros, ou seja, em um filtro que eu possuo restrições variáveis. Existe uma dificuldade muitas vezes de realizar a organização destes filtros, pois precisamos inserir muitos condicionais, IFs, para atender a necessidade.
Dessa forma estarei mostrando algumas dicas de como melhorar a organização de seu código.
Definição de Filtro
Um filtro é uma estrutura que nos permite inserir uma ou mais informações sobre um determinado assunto e realizar uma pesquisa deste. O exemplo mais clássico de um filtro é o Google, a Figura 01 exibe uma animação de uma busca utilizando o Google:
No caso de uma busca do Google, existe apenas 1 filtro. Mas nem todos os sistemas conseguem estabelecer telas que possuam apenas um campo de filtro, por exemplo a tela exibida na Figura 02, mostra uma área com vários campos que podem ser utilizados para buscas:
Repare que existem diversos filtros como ID, que representa a identificação da Categoria, o Name, que representa o nome da categoria, Created User, que criou a categoria e por fim a Created Date, que representa a data de criação no banco de dados daquela categoria. Nessa tela você pode pesquisar não inserindo nenhum campo, todos os campos ou uma mescla destas opções.
Exemplo de método de busca por filtros – padrão JDBC
Uma das formas mais simples de criar métodos de busca é inserir todos os campos de um filtro como parâmetros desse método. Vamos supor a seguinte classe Endereco, conforme mostra a Figura 03:
O código desta classe está representado abaixo:
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 |
public class Endereco { private Long id; private String rua; private Integer numero; private String complemento; private String bairro; private String cidade; private String estado; private String pais; public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } public String getRua() { return this.rua; } public void setRua(String rua) { this.rua = rua; } public Integer getNumero() { return this.numero; } public void setNumero(Integer numero) { this.numero = numero; } public String getComplemento() { return this.complemento; } public void setComplemento(String complemento) { this.complemento = complemento; } public String getBairro() { return this.bairro; } public void setBairro(String bairro) { this.bairro = bairro; } public String getCidade() { return this.cidade; } public void setCidade(String cidade) { this.cidade = cidade; } public String getEstado() { return this.estado; } public void setEstado(String estado) { this.estado = estado; } public String getPais() { return this.pais; } public void setPais(String pais) { this.pais = pais; } } |
Vamos definir um método de busca, no padrão JDBC, para todos os atributos deste método:
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
//Imports necessarios..... import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; //..... definicao da classe e outras coisas public List<Endereco> findByFilter(String rua, Integer numero, String complemento, String bairro, String cidade, String estado, String pais){ Connection c = null; PreparedStatement ps = null; ResultSet rs = null; try { boolean whereAdd = false; //definicao do SQL inicial StringBuilder sb = new StringBuilder("SELECT * FROM TB_ENDERECO as end "); //Campo rua if(rua != null){ if(!whereAdd){ sb.append(" WHERE "); whereAdd = true; } sb.append(" end.rua like ? "); }//fim do campo rua //Campo numero if(numero != null){ if(!whereAdd){ sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.numero = ? "); }//fim do campo numero //Campo complemento if(complemento != null){ if(!whereAdd){ sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.complemento like ? "); }//fim do campo complemento //Campo bairro if(bairro != null){ if(!whereAdd){ sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.bairro like ? "); }//fim do campo bairro //Campo cidade if(cidade != null){ if(!whereAdd){ sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.cidade like ? "); }//fim do campo cidade //Campo estado if(estado != null){ if(!whereAdd){ sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.estado like ? "); }//fim do campo estado //Campo pais if(pais != null){ if(!whereAdd){ sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.pais like ? "); }//fim do campo pais //obtem a instancia da classe Connection c = Conexao.getConnection(); ps = c.prepareStatement(sb.toString()); int pos = 0; //Campo rua if(rua != null){ ps.setObject(pos++, "%" + rua + "%"); }//fim do campo rua //Campo numero if(numero != null){ ps.setObject(pos++, numero); }//fim do campo numero //Campo complemento if(complemento != null){ ps.setObject(pos++, "%" + complemento + "%"); }//fim do campo complemento //Campo bairro if(bairro != null){ ps.setObject(pos++, "%" + bairro + "%"); }//fim do campo bairro //Campo cidade if(cidade != null){ ps.setObject(pos++, "%" + cidade + "%"); }//fim do campo cidade //Campo estado if(estado != null){ ps.setObject(pos++, "%" + estado + "%"); }//fim do campo estado //Campo pais if(pais != null){ ps.setObject(pos++, "%" + pais + "%"); }//fim do campo pais rs = ps.executeQuery(); List<Endereco> enderecos = new ArrayList<Endereco>(); while(rs.next()){ Endereco endereco = new Endereco(); endereco.setBairro(rs.getString("BAIRRO")); endereco.setCidade(rs.getString("CIDADE")); endereco.setComplemento(rs.getString("COMPLEMENTO")); endereco.setEstado(rs.getString("ESTADO")); endereco.setId(rs.getLong("ID")); endereco.setNumero(rs.getInt("NUMERO")); endereco.setPais(rs.getString("PAIS")); endereco.setRua(rs.getString("RUA")); enderecos.add(endereco); } return enderecos; } catch (SQLException e) { e.printStackTrace(); throw e; } finally { //Fecha a conexao de todos os recursos do JDBC Conexao.close(rs, ps, c); } } |
Esse método possui mais de 100 linhas, tornando a sua leitura mais complexa. Será que é possível organizá-lo de uma maneira a tornar mais fácil sua leitura? Sim é possível! Vamos analisar alguns pontos neste post e continuaremos a analisar nos próximos posts.
Campos de um Filtro x Parâmetros de um método
No caso do exemplo acima existem ao todo 7 parâmetros que representam o filtro de busca de uma tela de pesquisa de endereços. Assim, todos os campos que estão presentes no filtro são adicionados como parâmetros do método.
Isso é uma boa prática? Caso seja necessário adicionar mais campos no filtro de busca será necessário mexer nos parâmetros do método? Existe algum problema relacionado a isso?
Respondendo a primeira pergunta, isso não é uma boa prática, pois se a tela de pesquisa conter mais de 10, 15 campos, será necessário você adicionar 10, 15 parâmetros no seu método. Além disso, pode ser que esse método de busca seja utilizado em outras partes do sistema (ou talvez outros sistemas!), assim realizar uma mudança em sua assinatura, adicionando novos parâmetros, pode exigir mudanças de outros desenvolvedores no código, o que ocasiona retrabalho e gasto de tempo de projeto em correção de bugs.
Utilização de classes da Camada Model
Uma das formas de evitar que existam muitos parâmetros é utilizar a própria classe model base como Filtro. Assim, no método de exemplo, ao invés de passarmos 7 parâmetros, poderíamos passar apenas 1, uma instância de Endereco, que naturalmente já contém todos os campos de filtros, conforme mostra o código abaixo:
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
//Imports necessarios..... import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; //..... definicao da classe e outras coisas public List<Endereco> findByFilter(Endereco endereco) { Connection c = null; PreparedStatement ps = null; ResultSet rs = null; try { boolean whereAdd = false; // definicao do SQL inicial StringBuilder sb = new StringBuilder("SELECT * FROM TB_ENDERECO as end "); // Campo rua if (endereco.getRua() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } sb.append(" end.rua like ? "); } // fim do campo rua // Campo numero if (endereco.getNumero() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.numero = ? "); } // fim do campo numero // Campo complemento if (endereco.getComplemento() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.complemento like ? "); } // fim do campo complemento // Campo bairro if (endereco.getBairro() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.bairro like ? "); } // fim do campo bairro // Campo cidade if (endereco.getCidade() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.cidade like ? "); } // fim do campo cidade // Campo estado if (endereco.getEstado() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.estado like ? "); } // fim do campo estado // Campo pais if (endereco.getPais() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.pais like ? "); } // fim do campo pais // obtem a instancia da classe Connection c = Conexao.getConnection(); ps = c.prepareStatement(sb.toString()); int pos = 0; // Campo rua if (endereco.getRua() != null) { ps.setObject(pos++, "%" + endereco.getRua() + "%"); } // fim do campo rua // Campo numero if (endereco.getNumero() != null) { ps.setObject(pos++, endereco.getNumero()); } // fim do campo numero // Campo complemento if (endereco.getComplemento() != null) { ps.setObject(pos++, "%" + endereco.getComplemento() + "%"); } // fim do campo complemento // Campo bairro if (endereco.getBairro() != null) { ps.setObject(pos++, "%" + endereco.getBairro() + "%"); } // fim do campo bairro // Campo cidade if (endereco.getCidade() != null) { ps.setObject(pos++, "%" + endereco.getCidade() + "%"); } // fim do campo cidade // Campo estado if (endereco.getEstado() != null) { ps.setObject(pos++, "%" + endereco.getEstado() + "%"); } // fim do campo estado // Campo pais if (endereco.getPais() != null) { ps.setObject(pos++, "%" + endereco.getPais() + "%"); } // fim do campo pais rs = ps.executeQuery(); List<Endereco> enderecos = new ArrayList<Endereco>(); while (rs.next()) { Endereco endereco = new Endereco(); endereco.setBairro(rs.getString("BAIRRO")); endereco.setCidade(rs.getString("CIDADE")); endereco.setComplemento(rs.getString("COMPLEMENTO")); endereco.setEstado(rs.getString("ESTADO")); endereco.setId(rs.getLong("ID")); endereco.setNumero(rs.getInt("NUMERO")); endereco.setPais(rs.getString("PAIS")); endereco.setRua(rs.getString("RUA")); enderecos.add(endereco); } return enderecos; } catch (SQLException e) { e.printStackTrace(); throw e; } finally { // Fecha a conexao de todos os recursos do JDBC Conexao.close(rs, ps, c); } } |
Repare que as linhas marcadas foram alteradas, mas apenas porque agora nós estamos buscando as informações a partir da instância de endereco e não mais de cada parâmetro individualmente.
Mas e se o filtro de busca conter outros campos que não estão presentes na classe model?
Por exemplo, se o cliente pedir para que dentro do filtro fosse adicionado o campo de nome do cliente. Não seria possível adicionar esse nome do cliente na classe model Endereco, pois seria um campo apenas para esse filtro de busca desta tela de pesquisa. Assim é necessário, ao adotar essa solução de utilizar uma classe model, verificar se não haverão problemas com relação a inserção de novos campos de busca nesse filtro.
Utilização de classes Data Transfer Object
Antes de continuar a leitura…
Nesse artigo utilizamos o pattern DTO. Se você não sabe o que significa DTO, por favor leia o artigo.
Uma outra forma de utilizar é criar uma classe de Data Transfer Object ou DTO. A classe EnderecoDTO seria um bom substituto para o problema relacionado no tópico anterior, o qual poderíamos no futuro adicionar novos campos de acordo com a necessidade sem impactar em outros aspectos do projeto, evitando assim problemas de adicionar campos em classes que representam a abstração negocial do projeto. O código abaixo mostra a alteração ao inserir a classe DTO, repare que o código permaneceu idêntico ao código anterior, somente mudando o tipo da classe no parâmetro do método.
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
//Imports necessarios..... import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; //..... definicao da classe e outras coisas public List<Endereco> findByFilter(EnderecoDTO endereco){ Connection c = null; PreparedStatement ps = null; ResultSet rs = null; try { boolean whereAdd = false; // definicao do SQL inicial StringBuilder sb = new StringBuilder("SELECT * FROM TB_ENDERECO as end "); // Campo rua if (endereco.getRua() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } sb.append(" end.rua like ? "); } // fim do campo rua // Campo numero if (endereco.getNumero() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.numero = ? "); } // fim do campo numero // Campo complemento if (endereco.getComplemento() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.complemento like ? "); } // fim do campo complemento // Campo bairro if (endereco.getBairro() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.bairro like ? "); } // fim do campo bairro // Campo cidade if (endereco.getCidade() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.cidade like ? "); } // fim do campo cidade // Campo estado if (endereco.getEstado() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.estado like ? "); } // fim do campo estado // Campo pais if (endereco.getPais() != null) { if (!whereAdd) { sb.append(" WHERE "); whereAdd = true; } else { sb.append(" AND "); } sb.append(" end.pais like ? "); } // fim do campo pais // obtem a instancia da classe Connection c = Conexao.getConnection(); ps = c.prepareStatement(sb.toString()); int pos = 0; // Campo rua if (endereco.getRua() != null) { ps.setObject(pos++, "%" + endereco.getRua() + "%"); } // fim do campo rua // Campo numero if (endereco.getNumero() != null) { ps.setObject(pos++, endereco.getNumero()); } // fim do campo numero // Campo complemento if (endereco.getComplemento() != null) { ps.setObject(pos++, "%" + endereco.getComplemento() + "%"); } // fim do campo complemento // Campo bairro if (endereco.getBairro() != null) { ps.setObject(pos++, "%" + endereco.getBairro() + "%"); } // fim do campo bairro // Campo cidade if (endereco.getCidade() != null) { ps.setObject(pos++, "%" + endereco.getCidade() + "%"); } // fim do campo cidade // Campo estado if (endereco.getEstado() != null) { ps.setObject(pos++, "%" + endereco.getEstado() + "%"); } // fim do campo estado // Campo pais if (endereco.getPais() != null) { ps.setObject(pos++, "%" + endereco.getPais() + "%"); } // fim do campo pais rs = ps.executeQuery(); List<Endereco> enderecos = new ArrayList<Endereco>(); while (rs.next()) { Endereco endereco = new Endereco(); endereco.setBairro(rs.getString("BAIRRO")); endereco.setCidade(rs.getString("CIDADE")); endereco.setComplemento(rs.getString("COMPLEMENTO")); endereco.setEstado(rs.getString("ESTADO")); endereco.setId(rs.getLong("ID")); endereco.setNumero(rs.getInt("NUMERO")); endereco.setPais(rs.getString("PAIS")); endereco.setRua(rs.getString("RUA")); enderecos.add(endereco); } return enderecos; } catch (SQLException e) { e.printStackTrace(); throw e; } finally { // Fecha a conexao de todos os recursos do JDBC Conexao.close(rs, ps, c); } } |
Removendo o condicional para o WHERE e AND
Agora vamos começar a melhorar a forma de adicionar as informações referentes ao filtro. É necessário construir a remoção dos IFs relacionados as clausulas WHERE e AND. Vamos estabelecer um padrão de trabalho, assim o primeiro item a ser realizado é ter a certeza de que ao menos um atributo da classe DTO está preenchido. Então vamos colocar um if verificando se os atributos não estão preenchidos.
Uma observação aqui, já que poderíamos ter um método em outra camada, Business Control por exemplo ou no próprio DTO, que realizaria a validação se um dos itens estão preenchidos. Como não estamos trabalhando com várias camadas nesse artigo, mas apenas apresentando um método de exemplo, dessa forma, se faz necessário inserirmos esse IF aqui.
A partir desse IF é possível inserir o WHERE no SQL inicial, removendo assim os ifs relacionados a parte do WHERE.
Para remover os IFs da parte relacionada aos ANDs vamos adicionar uma condição com o SQL inicial (1=1). Isso servirá para que seja acrescentado um AND no começo da nova condição.
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
//Imports necessarios..... import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; //..... definicao da classe e outras coisas public List<Endereco> findByFilter(EnderecoDTO endereco) { if (endereco.getRua() == null && endereco.getNumero() == null && endereco.getComplemento() == null && endereco.getBairro() == null && endereco.getCidade() == null && endereco.getEstado() == null && endereco.getPais() == null) { throw new Exception("Favor preencher ao menos um campo do filtro de pesquisa!"); } // definicao do SQL inicial StringBuilder sb = new StringBuilder("SELECT * FROM TB_ENDERECO as end WHERE 1=1 "); Connection c = null; PreparedStatement ps = null; ResultSet rs = null; try { // Campo rua if (endereco.getRua() != null) { sb.append(" AND end.rua like ? "); } // fim do campo rua // Campo numero if (endereco.getNumero() != null) { sb.append(" AND end.numero = ? "); } // fim do campo numero // Campo complemento if (endereco.getComplemento() != null) { sb.append(" AND end.complemento like ? "); } // fim do campo complemento // Campo bairro if (endereco.getBairro() != null) { sb.append(" AND end.bairro like ? "); } // fim do campo bairro // Campo cidade if (endereco.getCidade() != null) { sb.append(" AND end.cidade like ? "); } // fim do campo cidade // Campo estado if (endereco.getEstado() != null) { sb.append(" AND end.estado like ? "); } // fim do campo estado // Campo pais if (endereco.getPais() != null) { sb.append(" AND end.pais like ? "); } // fim do campo pais // obtem a instancia da classe Connection c = Conexao.getConnection(); ps = c.prepareStatement(sb.toString()); int pos = 0; // Campo rua if (endereco.getRua() != null) { ps.setObject(pos++, "%" + endereco.getRua() + "%"); } // fim do campo rua // Campo numero if (endereco.getNumero() != null) { ps.setObject(pos++, endereco.getNumero()); } // fim do campo numero // Campo complemento if (endereco.getComplemento() != null) { ps.setObject(pos++, "%" + endereco.getComplemento() + "%"); } // fim do campo complemento // Campo bairro if (endereco.getBairro() != null) { ps.setObject(pos++, "%" + endereco.getBairro() + "%"); } // fim do campo bairro // Campo cidade if (endereco.getCidade() != null) { ps.setObject(pos++, "%" + endereco.getCidade() + "%"); } // fim do campo cidade // Campo estado if (endereco.getEstado() != null) { ps.setObject(pos++, "%" + endereco.getEstado() + "%"); } // fim do campo estado // Campo pais if (endereco.getPais() != null) { ps.setObject(pos++, "%" + endereco.getPais() + "%"); } // fim do campo pais rs = ps.executeQuery(); List<Endereco> enderecos = new ArrayList<Endereco>(); while (rs.next()) { Endereco e = new Endereco(); e.setBairro(rs.getString("BAIRRO")); e.setCidade(rs.getString("CIDADE")); e.setComplemento(rs.getString("COMPLEMENTO")); e.setEstado(rs.getString("ESTADO")); e.setId(rs.getLong("ID")); e.setNumero(rs.getInt("NUMERO")); e.setPais(rs.getString("PAIS")); e.setRua(rs.getString("RUA")); enderecos.add(e); } return enderecos; } catch (SQLException e) { e.printStackTrace(); throw new Exception("Problemas no sistema, por favor tente mais tarde"); } finally { // Fecha a conexao de todos os recursos do JDBC Conexao.close(rs, ps, c); } } |
Utilizando um Map para os parâmetros
Um Map, de acordo com a ciência da computação, é:
Na ciência da computação, existem duas definições da palavra Map. A primeira é um array associativo, um tipo de container que mapeia valores de um tipo para valores de outro tipo. Um exemplo disso é o STL map((API interface MAP – http://docs.oracle.com/javase/7/docs/api/java/util/Map.html)). A segunda definição vêm da programação funcional, na qual cada map é uma função que obtém uma lista e uma função, a qual é aplicada sobre todos os elementos da lista e, ao final, retorna uma lista de resultados.
Assim o Map pode ser utilizado para armazenar valores a partir de uma determinada chave. Dessa forma, vamos adaptar as passagens de parâmetros para o JDBC em nosso método de busca.
O primeiro trabalho a ser realizado é criar uma nova instância de java.util.Map. Como você talvez saiba, Map na verdade é uma interface, dessa forma devemos dar um new em uma de suas filhas para realizar a instanciação. Nesse exemplo iremos utilizar o java.util.HashMap, conforme a linha 30 do código abaixo ao criar a variável parameters.
Outro aspecto a ser feito é trazer a declaração da variável pos para o início do método e mudar o tipo para o wrapper, Integer, conforme linha 31, para não existir problemas na hora de informar a posição atual.
Por último e mais importante, iremos reduzir a duplicidade dos IFs, pois iremos trazer a atribuição de cada valor para dentro do Map e mais adiante no código iremos trabalhar a parte de atribuições no PreparedStatement, conforme mostram as linhas destacadas dentro de cada IF.
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
//Imports necessarios..... import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; //..... definicao da classe e outras coisas public List<Endereco> findByFilter(EnderecoDTO endereco) { if (endereco.getRua() == null && endereco.getNumero() == null && endereco.getComplemento() == null && endereco.getBairro() == null && endereco.getCidade() == null && endereco.getEstado() == null && endereco.getPais() == null) { throw new Exception("Favor preencher ao menos um campo do filtro de pesquisa!"); } // definicao do SQL inicial StringBuilder sb = new StringBuilder("SELECT * FROM TB_ENDERECO as end WHERE 1=1 "); Connection c = null; PreparedStatement ps = null; ResultSet rs = null; try { Map<Integer, Object> parameters = new HashMap<>(); Integer pos = 0; // Campo rua if (endereco.getRua() != null) { sb.append(" AND end.rua like ? "); parameters.put(pos++, "%" + endereco.getRua() + "%"); } // fim do campo rua // Campo numero if (endereco.getNumero() != null) { sb.append(" AND end.numero = ? "); parameters.put(pos++, endereco.getNumero()); } // fim do campo numero // Campo complemento if (endereco.getComplemento() != null) { sb.append(" AND end.complemento like ? "); parameters.put(pos++, "%" + endereco.getComplemento() + "%"); } // fim do campo complemento // Campo bairro if (endereco.getBairro() != null) { sb.append(" AND end.bairro like ? "); parameters.put(pos++, "%" + endereco.getBairro() + "%"); } // fim do campo bairro // Campo cidade if (endereco.getCidade() != null) { sb.append(" AND end.cidade like ? "); parameters.put(pos++, "%" + endereco.getCidade() + "%"); } // fim do campo cidade // Campo estado if (endereco.getEstado() != null) { sb.append(" AND end.estado like ? "); parameters.put(pos++, "%" + endereco.getEstado() + "%"); } // fim do campo estado // Campo pais if (endereco.getPais() != null) { sb.append(" AND end.pais like ? "); parameters.put(pos++, "%" + endereco.getPais() + "%"); } // fim do campo pais // obtem a instancia da classe Connection c = Conexao.getConnection(); ps = c.prepareStatement(sb.toString()); for (Entry<Integer, Object> entry : parameters.entrySet()) { ps.setObject(entry.getKey(), entry.getValue()); } rs = ps.executeQuery(); List<Endereco> enderecos = new ArrayList<Endereco>(); while (rs.next()) { Endereco e = new Endereco(); e.setBairro(rs.getString("BAIRRO")); e.setCidade(rs.getString("CIDADE")); e.setComplemento(rs.getString("COMPLEMENTO")); e.setEstado(rs.getString("ESTADO")); e.setId(rs.getLong("ID")); e.setNumero(rs.getInt("NUMERO")); e.setPais(rs.getString("PAIS")); e.setRua(rs.getString("RUA")); enderecos.add(e); } return enderecos; } catch (SQLException e) { e.printStackTrace(); throw new Exception("Problemas no sistema, por favor tente mais tarde"); } finally { // Fecha a conexao de todos os recursos do JDBC Conexao.close(rs, ps, c); } } |
finnaly{
Essa foi o artigo relacionado a organização de um código Java, utilizando SQL e JDBC para um método de busca com filtros. Existem outras coisas que você poderia fazer como a parte de obter as informações de um Result Set estar em um método separado, ou até mesmo os IFs estarem em outro método. Mas o ponto aqui é a utilização de coisas simples, como convenção de parâmetros, utilização de métodos da classe String e de estruturas de dados correspondentes para melhorar a escrita de um método que muitas vezes não temos muito o que melhorar.
Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!
Até um próximo post!
Leave a Reply