Boa Tarde amigos,
estou com um problema para montar uma consulta SQL, mas para fazê-los entender o meu problema, vou explicar o que quero.
O meu intuito é: ao visualizar um formulário de pesquisa de um filme por exemplo, o usuário deve preencher pelo menos um campo desse formulário (ou 2, 3, todos…enfim). Ao preencher esse formulário, esses dados são enviados para um servlet, que envia para a classe FilmeDAO. Nesta classe eu tenho o seguinte método:
public ResultSet listar(int idDiretor, int idAtor, int idGenero, int idLegenda, int idIdioma) throws SQLException{
ConnectionFactory conexao = new ConnectionFactory();
conexao.conectar();
PreparedStatement pst = null;
ResultSet rs = null;
try{
pst = conexao.conn.prepareStatement(SELECT_BY_DADOS);
if(idDiretor==0){
pst.setString(1, "\" or \"x\"=\"x");
}else{
pst.setInt(1, idDiretor);
}
if(idAtor==0){
pst.setString(2, "\" or \"x\"=\"x");
}else{
pst.setInt(2, idAtor);
}
if(idIdioma==0){
pst.setString(3, "\" or \"x\"=\"x");
}else{
pst.setInt(3, idIdioma);
}
if(idGenero==0){
pst.setString(4, "\" or \"x\"=\"x");
}else{
pst.setInt(4, idGenero);
}
if(idLegenda==0){
pst.setString(5, "\" or \"x\"=\"x");
}else{
pst.setInt(5, idLegenda);
}
if(getNome()==null){
pst.setString(6, "\" or \"x\"=\"x");
}else{
pst.setString(6, getNome()+"%");
}
if(getDataLancamento()==null){
pst.setString(7, "\" or \"x\"=\"x");
}else{
pst.setString(7, getDataLancamento());
}
if(getLancamento()==true){
pst.setBoolean(8, getLancamento());
}else{
pst.setString(8, "\" or \"x\"=\"x");
}
rs = pst.executeQuery();
}catch(SQLException e){
throw new SQLException("Erro na execucao do sql.");
}
return rs;
}
Como vocês podem ver, o próprio método faz (ou tenta fazer) uma manipulação dos dados que ele receber, verificando se cada dado que ele recebeu é nulo ou não, e se for nulo, ele irá injetar na query uma espécie de SQL Injection que irá fazer com que a consulta desconsidere aquele refinamento de dados (pelo menos na minha pobre mente funcionaria assim).
Para ver se essa gambiarra louca funcionaria, eu testei pelo MySQL WorkBench a seguinte query:
select distinct f.* from filme f
inner join idioma_filme idf on f.id_filme = idf.id_filme
inner join idioma i on idf.id_idioma = i.id_idioma
inner join legenda_filme lf on lf.id_filme = f.id_filme
inner join legenda l on l.id_legenda = lf.id_legenda
inner join ator_filme af on f.id_filme = af.id_filme
inner join ator a on af.id_ator = a.id_ator
inner join filme_genero fg on fg.id_filme = f.id_filme
inner join genero g on g.id_genero = fg.id_genero
where (f.id_diretor = "" or "x"="x") and (a.id_ator = "" or "x"="x") and (i.id_idioma = "" or "x"="x") and (g.id_genero = "" or "x"="x")
and (l.id_legenda = "" or "x"="x") and (f.nome_filme like "" or "x"="x") and (f.data_lancamento = "" or "x"="x")
and (f.lancamento = "" or "x"="x");
A query original seria:
private static final String SELECT_BY_DADOS = "select distinct f.* from filme f "
+ "inner join idioma_filme idf on f.id_filme = idf.id_filme "
+ "inner join idioma i on idf.id_idioma = i.id_idioma "
+ "inner join legenda_filme lf on lf.id_filme = f.id_filme "
+ "inner join legenda l on l.id_legenda = lf.id_legenda "
+ "inner join ator_filme af on f.id_filme = af.id_filme "
+ "inner join ator a on af.id_ator = a.id_ator "
+ "inner join filme_genero fg on fg.id_filme = f.id_filme "
+ "inner join genero g on g.id_genero = fg.id_genero "
+ "where (f.id_diretor = ?) and (a.id_ator = ?) and (i.id_idioma = ?) and (g.id_genero = ?) "
+ "and (l.id_legenda = ?) and (f.nome_filme like ?) and (f.data_lancamento = ?) "
+ "and (f.lancamento = ?)";
Ou seja, eu tentei simular a query no Workbench, supondo que todos os dados fossem nulos, subentendendo-se que o usuário iria querer todos os filmes cadastrados. Ao executar essa query no Workbench, ela funciona exatamente como eu quero, ela traz todos os filmes cadastrados. Se eu colocar que o usuário sabe somente que o nome do filme começa com “a”, ele me trouxe todos os filmes que começavam com “a”, e beleza, todo mundo é bonito e bem dotado. O problema é quando eu tento fazer o mesmo usando o PreparedStatement da forma que usei no codigo acima. Ele simplesmente não me retorna resultado algum. Ele só me retorna resultado se eu setar todos os campos da pesquisa do sql.
Eu sei que posso não ter sido muito claro em minha dúvida, e também ficou meio confuso…mas isso se trata de um projeto final de um curso técnico, e preciso adicionar esse tipo de funcionalidade ao meu sistema. Desconfio que o problema está na forma com que o pst.setString() seta aquela pequena string na hora de executar a consulta.
Peço que qualquer um que saiba como resolver o problema, me ajude. Se alguém souber também uma forma melhor e mais inteligente de construir um formulário com a mesma funcionalidade, por favor, me explique.
Estarei no aguardo.