• Skip to primary navigation
  • Skip to content

Mauda

IT, Java and Music

Graduação   SCJP   Mestrado
  • Apresentação
  • Certificação Java
  • JPA
    • Exceptions
  • JSF
  • Versionamento
  • Contato

HQL – Dicas para Organizar um método de busca com Filtros

September 21, 2015 by Mauda 4 Comments

Conteúdo do Post:
  1. Definição de Filtro
  2. Exemplo de método de busca por filtros – padrão HQL
  3. Campos de um Filtro x Parâmetros de um método
  4. Utilização de classes da Camada Model
  5. Utilização de classes Data Transfer Object
  6. Removendo o condicional para o WHERE e AND
  7. Utilizando um Map para os parâmetros
  8. finnaly{

Olá Pessoal, tudo bom?

Esse artigo está relacionado ao artigo de organização de método de busca com SQL, mas agora focado em HQL, com classes relacionadas ao Hibernate.

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:

Figura 01 – Animação de uma pesquisa com o Google – Credito 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:

Figura 02 – Exemplo de uma tela com vários filtros de pesquisa -Crédito: https://mscblogs.blob.core.windows.net

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 HQL

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:

Figura 03 – Classe Endereco – Representação UML

O código desta classe está representado abaixo:

Java
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 HQL, para todos os atributos deste método:

Java
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
//Imports necessarios.....
 
import java.sql.SQLException;
import java.util.Collection;
 
import org.hibernate.Query;
import org.hibernate.Session;
 
//..... definicao da classe e outras coisas
 
    @SuppressWarnings("unchecked")
    public Collection<Endereco> findByFilter(String rua, Integer numero, String complemento, String bairro, String cidade, String estado, String pais) {
        Session session = HibernateUtil.getSession();
        try {
            boolean whereAdd = false;
 
            // definicao do HQL inicial
            StringBuilder sb = new StringBuilder("FROM Endereco as end ");
 
            // Campo rua
            if (rua != null) {
                if (!whereAdd) {
                    sb.append(" WHERE ");
                    whereAdd = true;
                }
                sb.append(" end.rua like :rua ");
            } // fim do campo rua
 
            // Campo numero
            if (numero != null) {
                if (!whereAdd) {
                    sb.append(" WHERE ");
                    whereAdd = true;
                } else {
                    sb.append(" AND ");
                }
                sb.append(" end.numero = :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 :complemento ");
            } // 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 :bairro ");
            } // 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 :cidade ");
            } // 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 :estado ");
            } // 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 :pais ");
            } // fim do campo pais
 
            Query query = session.createQuery(sb.toString());
 
            // Campo rua
            if (rua != null) {
                query.setParameter("rua", "%" + rua + "%");
            } // fim do campo rua
 
            // Campo numero
            if (numero != null) {
                query.setParameter("numero", numero);
            } // fim do campo numero
 
            // Campo complemento
            if (complemento != null) {
                query.setParameter("complemento", "%" + complemento + "%");
            } // fim do campo complemento
 
            // Campo bairro
            if (bairro != null) {
                query.setParameter("bairro", "%" + bairro + "%");
            } // fim do campo bairro
 
            // Campo cidade
            if (cidade != null) {
                query.setParameter("cidade", "%" + cidade + "%");
            } // fim do campo cidade
 
            // Campo estado
            if (estado != null) {
                query.setParameter("estado", "%" + estado + "%");
            } // fim do campo estado
 
            // Campo pais
            if (pais != null) {
                query.setParameter("pais", "%" + pais + "%");
            } // fim do campo pais
 
            return query.list();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        } finally {
            // Fecha a conexao da session
            session.close();
        }
    }

 

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:

Java
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
//Imports necessarios.....
 
import java.sql.SQLException;
import java.util.Collection;
 
import org.hibernate.Query;
import org.hibernate.Session;
 
import br.com.mauda.seminario.cientificos.dao.util.HibernateUtil;
 
//..... definicao da classe e outras coisas
 
    @SuppressWarnings("unchecked")
    public Collection<Endereco> findByFilter(Endereco endereco) {
        Session session = HibernateUtil.getSession();
        try {
            boolean whereAdd = false;
 
            // definicao do HQL inicial
            StringBuilder sb = new StringBuilder("FROM Endereco as end ");
 
            // Campo rua
            if (endereco.getRua() != null) {
                if (!whereAdd) {
                    sb.append(" WHERE ");
                    whereAdd = true;
                }
                sb.append(" end.rua like :rua ");
            } // 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 = :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 :complemento ");
            } // 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 :bairro ");
            } // 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 :cidade ");
            } // 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 :estado ");
            } // 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 :pais ");
            } // fim do campo pais
 
            Query query = session.createQuery(sb.toString());
 
            // Campo rua
            if (endereco.getRua() != null) {
                query.setParameter("rua", "%" + endereco.getRua() + "%");
            } // fim do campo rua
 
            // Campo numero
            if (endereco.getNumero() != null) {
                query.setParameter("numero", endereco.getNumero());
            } // fim do campo numero
 
            // Campo complemento
            if (endereco.getComplemento() != null) {
                query.setParameter("complemento", "%" + endereco.getComplemento() + "%");
            } // fim do campo complemento
 
            // Campo bairro
            if (endereco.getBairro() != null) {
                query.setParameter("bairro", "%" + endereco.getBairro() + "%");
            } // fim do campo bairro
 
            // Campo cidade
            if (endereco.getCidade() != null) {
                query.setParameter("cidade", "%" + endereco.getCidade() + "%");
            } // fim do campo cidade
 
            // Campo estado
            if (endereco.getEstado() != null) {
                query.setParameter("estado", "%" + endereco.getEstado() + "%");
            } // fim do campo estado
 
            // Campo pais
            if (endereco.getPais() != null) {
                query.setParameter("pais", "%" + endereco.getPais() + "%");
            } // fim do campo pais
 
            return query.list();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        } finally {
            // Fecha a conexao da session
            session.close();
        }
    }

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.

Java
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
//Imports necessarios.....
 
import java.sql.SQLException;
import java.util.Collection;
 
import org.hibernate.Query;
import org.hibernate.Session;
 
import br.com.mauda.seminario.cientificos.dao.util.HibernateUtil;
 
//..... definicao da classe e outras coisas
 
    @SuppressWarnings("unchecked")
    public Collection<Endereco> findByFilter(EnderecoDTO endereco){
        Session session = HibernateUtil.getSession();
        try {
            boolean whereAdd = false;
 
            // definicao do HQL inicial
            StringBuilder sb = new StringBuilder("FROM Endereco as end ");
 
            // Campo rua
            if (endereco.getRua() != null) {
                if (!whereAdd) {
                    sb.append(" WHERE ");
                    whereAdd = true;
                }
                sb.append(" end.rua like :rua ");
            } // 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 = :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 :complemento ");
            } // 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 :bairro ");
            } // 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 :cidade ");
            } // 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 :estado ");
            } // 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 :pais ");
            } // fim do campo pais
 
            Query query = session.createQuery(sb.toString());
 
            // Campo rua
            if (endereco.getRua() != null) {
                query.setParameter("rua", "%" + endereco.getRua() + "%");
            } // fim do campo rua
 
            // Campo numero
            if (endereco.getNumero() != null) {
                query.setParameter("numero", endereco.getNumero());
            } // fim do campo numero
 
            // Campo complemento
            if (endereco.getComplemento() != null) {
                query.setParameter("complemento", "%" + endereco.getComplemento() + "%");
            } // fim do campo complemento
 
            // Campo bairro
            if (endereco.getBairro() != null) {
                query.setParameter("bairro", "%" + endereco.getBairro() + "%");
            } // fim do campo bairro
 
            // Campo cidade
            if (endereco.getCidade() != null) {
                query.setParameter("cidade", "%" + endereco.getCidade() + "%");
            } // fim do campo cidade
 
            // Campo estado
            if (endereco.getEstado() != null) {
                query.setParameter("estado", "%" + endereco.getEstado() + "%");
            } // fim do campo estado
 
            // Campo pais
            if (endereco.getPais() != null) {
                query.setParameter("pais", "%" + endereco.getPais() + "%");
            } // fim do campo pais
 
            return query.list();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        } finally {
            // Fecha a conexao da session
            session.close();
        }
    }

 

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.

Java
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
//Imports necessarios.....
 
import java.sql.SQLException;
import java.util.Collection;
 
import org.hibernate.Query;
import org.hibernate.Session;
 
import br.com.mauda.seminario.cientificos.dao.util.HibernateUtil;
 
//..... definicao da classe e outras coisas
 
    @SuppressWarnings("unchecked")
    public Collection<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!");
        }
 
        Session session = HibernateUtil.getSession();
        try {
            // definicao do HQL inicial
            StringBuilder sb = new StringBuilder("FROM Endereco as end WHERE 1=1 ");
 
            // Campo rua
            if (endereco.getRua() != null) {
                sb.append(" AND end.rua like :rua ");
            } // fim do campo rua
 
            // Campo numero
            if (endereco.getNumero() != null) {
                sb.append(" AND end.numero = :numero ");
            } // fim do campo numero
 
            // Campo complemento
            if (endereco.getComplemento() != null) {
                sb.append(" AND end.complemento like :complemento ");
            } // fim do campo complemento
 
            // Campo bairro
            if (endereco.getBairro() != null) {
                sb.append(" AND end.bairro like :bairro ");
            } // fim do campo bairro
 
            // Campo cidade
            if (endereco.getCidade() != null) {
                sb.append(" AND end.cidade like :cidade ");
            } // fim do campo cidade
 
            // Campo estado
            if (endereco.getEstado() != null) {
                sb.append(" AND end.estado like :estado ");
            } // fim do campo estado
 
            // Campo pais
            if (endereco.getPais() != null) {
                sb.append(" AND end.pais like :pais ");
            } // fim do campo pais
 
            Query query = session.createQuery(sb.toString());
 
            // Campo rua
            if (endereco.getRua() != null) {
                query.setParameter("rua", "%" + endereco.getRua() + "%");
            } // fim do campo rua
 
            // Campo numero
            if (endereco.getNumero() != null) {
                query.setParameter("numero", endereco.getNumero());
            } // fim do campo numero
 
            // Campo complemento
            if (endereco.getComplemento() != null) {
                query.setParameter("complemento", "%" + endereco.getComplemento() + "%");
            } // fim do campo complemento
 
            // Campo bairro
            if (endereco.getBairro() != null) {
                query.setParameter("bairro", "%" + endereco.getBairro() + "%");
            } // fim do campo bairro
 
            // Campo cidade
            if (endereco.getCidade() != null) {
                query.setParameter("cidade", "%" + endereco.getCidade() + "%");
            } // fim do campo cidade
 
            // Campo estado
            if (endereco.getEstado() != null) {
                query.setParameter("estado", "%" + endereco.getEstado() + "%");
            } // fim do campo estado
 
            // Campo pais
            if (endereco.getPais() != null) {
                query.setParameter("pais", "%" + endereco.getPais() + "%");
            } // fim do campo pais
 
            return query.list();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        } finally {
            // Fecha a conexao da session
            session.close();
        }
    }

 

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 3 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.

Java
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
//Imports necessarios.....
 
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
 
import org.hibernate.Query;
import org.hibernate.Session;
 
import br.com.mauda.seminario.cientificos.dao.util.HibernateUtil;
 
//..... definicao da classe e outras coisas
 
    @SuppressWarnings("unchecked")
    public Collection<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!");
        }
 
        Session session = HibernateUtil.getSession();
        try {
            // definicao do HQL inicial
            StringBuilder sb = new StringBuilder("FROM Endereco as end WHERE 1=1 ");
            Map<String, Object> parameters = new HashMap<>();
 
            // Campo rua
            if (endereco.getRua() != null) {
                sb.append(" AND end.rua like :rua ");
                parameters.put("rua", "%" + endereco.getRua() + "%");
            } // fim do campo rua
 
            // Campo numero
            if (endereco.getNumero() != null) {
                sb.append(" AND end.numero = :numero ");
                parameters.put("numero", endereco.getNumero());
            } // fim do campo numero
 
            // Campo complemento
            if (endereco.getComplemento() != null) {
                sb.append(" AND end.complemento like :complemento ");
                parameters.put("complemento", "%" + endereco.getComplemento() + "%");
            } // fim do campo complemento
 
            // Campo bairro
            if (endereco.getBairro() != null) {
                sb.append(" AND end.bairro like :bairro ");
                parameters.put("bairro", "%" + endereco.getBairro() + "%");
            } // fim do campo bairro
 
            // Campo cidade
            if (endereco.getCidade() != null) {
                sb.append(" AND end.cidade like :cidade ");
                parameters.put("cidade", "%" + endereco.getCidade() + "%");
            } // fim do campo cidade
 
            // Campo estado
            if (endereco.getEstado() != null) {
                sb.append(" AND end.estado like :estado ");
                parameters.put("estado", "%" + endereco.getEstado() + "%");
            } // fim do campo estado
 
            // Campo pais
            if (endereco.getPais() != null) {
                sb.append(" AND end.pais like :pais ");
                parameters.put("pais", "%" + endereco.getPais() + "%");
            } // fim do campo pais
 
            Query query = session.createQuery(sb.toString());
 
            for (Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
 
            return query.list();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        } finally {
            // Fecha a conexao da session
            session.close();
        }
    }

finnaly{

Essa foi o artigo relacionado a organização de um código Java, utilizando HQL 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!

Filed Under: Hibernate, Java, JPA Tagged With: Hibernate, HQL, Java, JPA, JPAQL, SQL

About Mauda

Mestre em Informática, Analista de Sistemas, Professor, SCJP e Baterista. Desde 2002 trabalhando no mundo Java e ensinando pessoas sobre desenvolvimento de sistemas. Mais informações

Reader Interactions

Comments

  1. Danilo says

    October 3, 2017 at 4:32 pm

    trocar para ++pos e então funcionará bem..

    Reply
    • Mauda says

      October 6, 2017 at 2:49 pm

      Olá Danilo, tudo bom?

      Não entendi o seu comentário, pois o inicio da variável pos é com 0, assim o primeiro valor a ser inserido será 0. Se for o ++pos você terá que iniciar com -1 para que tenha o mesmo efeito.

      Obrigado.

      Reply
  2. Ivandro says

    February 28, 2018 at 11:56 am

    Excelente dica para consultas dinâmicas.
    Você também pode usar o artifício técnico “where 1 = 1” e alterar os appends para sb.append(“AND end.complemento like ? “). Isso evitaria ter que remover o último AND no prepareStatement.

    Reply
    • Mauda says

      March 4, 2018 at 10:03 pm

      Olá Ivandro, tudo bom?

      Excelente dica! Realmente ajuda a evitar a remoção do ultimo AND e garante um where inicial.

      Valeu!

      Grande abraço!

      Reply

Leave a Reply to Mauda Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Advertisements

Copyright © 2025 · Genesis Framework · WordPress · Log in