Como descobrir se em um select foi setado um parametro
20 respostas
M
magni
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
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
AbelBueno
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.
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.
Mas estou curioso pra saber qual erro no código do autor.
Então tá né…
M
magni
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
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
magni
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
AbelBueno
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
AbelBueno
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.