Como descobrir se em um select foi setado um parametro

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…

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+"%"); }

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

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

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

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?

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.

[quote=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.[/quote]Então tá né…

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

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()

[quote=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()[/quote]

è 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…

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=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?

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

[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]

Como executou seu teste?

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.