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() + "%'";
}
[quote=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() + "%'";
}
[/quote]É 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+"%");
}
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)
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.
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.
[/quote]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
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?
[quote=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?[/quote] 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?
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
[quote=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.[/quote]Fez um teste de carga também?
[quote=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…[/quote]
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.
[quote=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.[/quote]
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.
Não exatamente… com a sugestão que dei acima não é necessário.
[quote=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.[/quote]
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.