Como descobrir se em um select foi setado um parametro

20 respostas
M

Bom dia

Tenho o seguinte código:

if(usuario != null && (descricao != null && !descricao.trim().isEmpty())){
				sql.append("where u = :usuario and UPPER(pl.descricao) like UPPER(:descricao)");
			}else{
				sql.append("where u = :usuario");
			}

A minha duvida é a seguinte… depois de execultado esse if eu vo ter que saber se foi setado a “descricao” para dai poder dar um

query.setParameter("descricao", "%"+descricao+"%");

Alguém sabe como eu poderia descobrir isso?

Ja tentei o código abaixo mas da erro:

if(query.getParameters().contains("descricao")){
				query.setParameter("descricao", "%"+descricao+"%");
			}

Caso alguém poder me ajudar…

20 Respostas

marciosouzajunior

Olá, uma forma diferente de fazer isso é usando querys nativas:

String query = "SELECT * FROM tabela WHERE 1=1 ";

Depois você vai concatenando strings conforme as validações:

if (!txDescricao.getText().equals("")) {

            query += " AND descricao LIKE '%" + txDescricao.getText() + "%'";

        }

        if (!txCodigo.getText().equals("")) {

            query += " AND codigo LIKE '%" + txCodigo.getText() + "%'";

        }
Hebert_Coelho

marciosouzajunior:
Olá, uma forma diferente de fazer isso é usando querys nativas:

String query = "SELECT * FROM tabela WHERE 1=1 ";

Depois você vai concatenando strings conforme as validações:

if (!txDescricao.getText().equals("")) {

            query += " AND descricao LIKE '%" + txDescricao.getText() + "%'";

        }

        if (!txCodigo.getText().equals("")) {

            query += " AND codigo LIKE '%" + txCodigo.getText() + "%'";

        }

É aconselhado a nunca fazer concatenação de string em parâmetros. Você pode sofrer ataque de sql injection.
Oque é que foi que deu erro? if(query.getParameters().contains("descricao")){ query.setParameter("descricao", "%"+descricao+"%"); }

marciosouzajunior

Nunca faça isso se estiver validando um login por exemplo. Nos outros casos avalie o risco.

Hebert_Coelho

Pode me mostrar um exemplo de em qual caso isso não vale a pena? (sem ofença tah)
Todo livro que já li, todos falaram para nunca fazer isso e nunca me mostraram exemplos onde não haveriam problema. (falando de web)

A

Não é apenas por segurança que se utiliza parâmetros, apesar deste motivo ser suficiente para usar sempre.

Você pode ter ganho de performance, pois o banco geralmente manterá sua query “parseada” quando utiliza parâmetros.

Outra vantagem é que você elimina problemas com formatos. Data é um caso típico que sempre gera problemas.

Um bom caso e raro caso para não usar parâmetro é quando quer forçar dois planos diferentes para queries semelhantes.
Neste caso, mandando o valor concatenado na query, fará o banco fazer novamente o parsing daquela instrução.

Hebert_Coelho

Não é apenas por segurança que se utiliza parâmetros, apesar deste motivo ser suficiente para usar sempre.

Você pode ter ganho de performance, pois o banco geralmente manterá sua query “parseada” quando utiliza parâmetros.

Outra vantagem é que você elimina problemas com formatos. Data é um caso típico que sempre gera problemas.

Um bom caso e raro caso para não usar parâmetro é quando quer forçar dois planos diferentes para queries semelhantes.
Neste caso, mandando o valor concatenado na query, fará o banco fazer novamente o parsing daquela instrução.

Aproveitando que você já falou tudo, eu esqueci de falar do post que publiquei hoje de manhã e fala sobre tudo isso aí que você acabou de falar: http://uaihebert.com/?p=1137

Tem isso tudo que você falou e mais. [=

marciosouzajunior

Não digo que não vale a pena usar, mas no caso de montar a query dinamicamente sabendo que o usuário vai passar parâmetros ou não, como ficaria a implementação disso?

Hebert_Coelho

marciosouzajunior:
Não digo que não vale a pena usar, mas no caso de montar a query dinamicamente sabendo que o usuário vai passar parâmetros ou não, como ficaria a implementação disso?
Mole:

String sql = "select * from pessoa where 1=1"; if(valor = true){ sql.append("and valor = :valor"); }
e depois cria a query e o parâmetro.

Agora, em qual caso vale a pena concatenar a string?

marciosouzajunior

Vale a pena quando você achar que segurança, performance e formato não serão problemas. :stuck_out_tongue:

Mas estou curioso pra saber qual erro no código do autor.

Hebert_Coelho

marciosouzajunior:
Vale a pena quando você achar que segurança, performance e formato não serão problemas. :stuck_out_tongue:

Mas estou curioso pra saber qual erro no código do autor.

Então tá né…

M

Ta ai a minha pilha de erro…
Outra coisa que eu esqueci de falar, essa consulta que eu to montando é com jpql… usando jpa2
E sobre a contatenação de String na query query.setParameter(“descricao”, “%”+descricao+"%");
é um caso bem específico, e que não prejudica o sistema com nada

Caused by: org.hibernate.QueryException: Not all named parameters have been set: [descricao] //
	at org.hibernate.impl.AbstractQueryImpl.verifyParameters(AbstractQueryImpl.java:339)
	at org.hibernate.impl.AbstractQueryImpl.verifyParameters(AbstractQueryImpl.java:323)
	at org.hibernate.impl.QueryImpl.list(QueryImpl.java:98)
	at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:241)
	... 86 more
Hebert_Coelho

Mas aqui não tem problema nenhum: query.setParameter(“descricao”, “%”+descricao+"%");

Essa mensagem tá falando que você não preencheu.

Seu if tá furando.
Pq vc não faz o if igual vc já fez? descricao != null && !descricao.trim().isEmpty()

M

jakefrog:
Mas aqui não tem problema nenhum: query.setParameter(“descricao”, “%”+descricao+"%");

Essa mensagem tá falando que você não preencheu.

Seu if tá furando.
Pq vc não faz o if igual vc já fez? descricao != null && !descricao.trim().isEmpty()

è que eu tava procurando uma solução que não seja copiar a condição do if de cima…

Mas pelo jeito não vai ter outra opção…

marciosouzajunior

Tá aí uma vantagem de concatenar, a manutenção do código fica mais fácil.

Só pra constar também, fiz testes aqui utilizando o profiler do netbens e notei que se tiver diferença de performance é quase imperceptível.

Hebert_Coelho

marciosouzajunior:
Tá aí uma vantagem de concatenar, a manutenção do código fica mais fácil.

Só pra constar também, fiz testes aqui utilizando o profiler do netbens e notei que se tiver diferença de performance é quase imperceptível.

Fez um teste de carga também?

marciosouzajunior

Me indica algo em linux que faça teste de carga em aplicações desktop?

A

magni:
è que eu tava procurando uma solução que não seja copiar a condição do if de cima…

Mas pelo jeito não vai ter outra opção…

Na verdade, você só precisa escrever o if uma vez e “lembrar” o resultado de cada decisão.

Use um Map<String,Object> para guardar todos os parametros que precisam existir.

Na hora de setar o parâmetro na query, você lê diretamente o Map.

Essa facilidade de manutenção é bem relativa.
Utilizando parâmetro o número de concatenações é menor, portanto menos sujeita a erros.

marciosouzajunior:

Só pra constar também, fiz testes aqui utilizando o profiler do netbens e notei que se tiver diferença de performance é quase imperceptível.

Como executou seu teste?

marciosouzajunior

Mas depois que você concatenou e funcionou, é tranquilo de manter.
Com o parâmetro tem que usar mais if’s depois pra verificar se o usuário entrou com o parâmetro.
Isso significa que você terá que alterar 2 partes do código se for colocar ou retirar algum parâmetro.

Criei uma classe simples que se conecta ao banco. A classe executa um select que retorna 2900 linhas.
Medi os tempos utilizando o profiler do netbeans utilizando parâmetro e concatenando.
Tirei a média de 5 tempos tomados, concatenando ficou com 385 e com parâmetro 391.
Penso que se você está recriando a query a cada consulta, não haverá vantagem em nenhum dos casos.

A

Não exatamente… com a sugestão que dei acima não é necessário.

marciosouzajunior:

Criei uma classe simples que se conecta ao banco. A classe executa um select que retorna 2900 linhas.
Medi os tempos utilizando o profiler do netbeans utilizando parâmetro e concatenando.
Tirei a média de 5 tempos tomados, concatenando ficou com 385 e com parâmetro 391.
Penso que se você está recriando a query a cada consulta, não haverá vantagem em nenhum dos casos.

O tempo que você ganha com o parâmetro é no parse da query pelo banco de dados.
Suponha que a query leva 1ms para ser parseada e 1ms para execução. Eliminando o campo dá uma melhora de 50%.
Não é em uma query que você vai notar a diferença, é no constante uso da mesma query com valores de parametros diferentes.

Experimente o seguinte teste:

  • Preencha uma tabela com muitos registros (uns 100k)
  • Crie um método que faça um for até 10k para executar a query pela chave primária Sem parametro
  • Crie um método que faça um for até 10k para executar a query pela chave primária Com parametro
  • Crie um for (até 20, por ex) chamando cada método desse alternadamente, contando o tempo.
    (Essa parte é para deixar o banco de dados e a jvm se aquecerem).

Nas últimas medições poderá notar uma diferença grande entre os dois métodos.
No teste que criei aqui a diferença foi de mais de 10x.

Hebert_Coelho

Eu nunca concatenei parâmetros e nunca vi dificuldade em manter por setParameter.

Se a pessoa quiser, ela pode inclusive criar um modo dinâmico de popular parâmetro.

Até hoje nunca li um livro que alguma situação falasse/indicasse o uso de concatenação viu.

Por isso q eu perguntei por um exemplo, sempre estou disposto a ouvir novas soluções.

Criado 20 de abril de 2012
Ultima resposta 20 de abr. de 2012
Respostas 20
Participantes 4