JPA Consultas e Dicas

e ai pessoal
vamos ver se consigo atrair o jakefrog, mas quem quiser ajudar, manda ai a sugestão

vamos lá
tenho uma consulta com vários parâmetros, mas como o nosso amigo ai de cima não recomenda o uso de concatenação de Strings, não sei como fazer
bem, tenho a seguinte situação: em uma tela JSF existe vários campos para pesquisar, mas nenhum campo é obrigatório, mas pelo menus um deve ser preenchido
a ideia original era fazer mais ou menos assim:

//montando a consulta String consulta = "minha consulta"; if (pesquisa.getCampoUm() != null) { consulta = consulta +pesquisa.getCampoUm().toString(); } if (pesquisa.getCampoDois() != null) { consulta = consulta +pesquisa.getCampoDoisr(); } ...... //rodar a consulta

mas não é recomendado, por causa da JPQL Injection
então alguma ideia?

Ola!

Eu faria assim…

//lista dos parametros da pesquisa
Map<String, Object> valores = new HashMap<String, Object>();
 //montando a consulta
String consulta = "minha consulta ";
if (pesquisa.getCampoUm() != null) {
	consulta = consulta + " campoUm = :valor1";
	valores.put("valor1", pesquisa.getCampoUm());
}
if (pesquisa.getCampoDois() != null) {
	consulta = consulta + " campoDois = :valor2";
	valores.put("valor2", pesquisa.getCampoDois());
}

//cria a consulta normal
Query query = createQuery(consulta);
//joga os parametros
for (Entry<String, Object> valor : valores.entrySet()) {
	query.setParameter(valor.getKey(), valor.getValue());
}
//rodar a consulta

Embora a concatenação exista, ela não usa valores externos, apenas variaveis, os parametros continuam sendo preenchidos através do query.setParameter.

sem falar que estou usando JPQL e não SQL
mas ainda acho que pode causar uma injeção,
mas por enquanto vai ficando assim,
e eu até que tentei usar o

StringBuffer consulta = new StringBuffer("minha consulta");
        if(pesquisa.getCampoUm() != null){
            consulta.append("and condição like " + "%").append(pesquisa.getCampoUm()).append("%");
        }

mas me deu erro, acho que é por que estou tentando rodar JPQL e HQL numa só,
claro que da problema, mas não sei como é o HQL, só vi esse exemplo no GUJ:


StringBuffer sql = new StringBuffer();  
sql.append("select * from xpto where 1=1")  
     
if(parametro1!=null){    
sql.append(" and parametro1="+parametro1);    
}    
if(parametro2!=null){    
sql.append(" and parametro2="+parametro2);    
}   
  
Query query = entityManager().createQuery(sql.toString());  
                             
objetoRetorno = query.getSingleResult(); | query.getResultList(); //retorna um objeto | uma lista  

mas estou usando o EclipseLink, não o Hibernate, então empaquei

Opa, muito bom esse blog aí hein?! :lol: :lol: :lol:

Rapaz, eu faço igual ao que o vi-gb falou. E funciona para eclipse link também. [=

[quote=jaissonduarte]e ai pessoal
vamos ver se consigo atrair o jakefrog, mas quem quiser ajudar, manda ai a sugestão
… [/quote]
Hahahahaa, muito bom! eu li o título e lembrei do blog dele também

voltando a esse tópico

como ficaria uma consulta com join?
tipo eu tenho que colocar todos os join na

String consulta = "SELECT d FROM ..... ";
ou eu posso adiciona-los se os campos que precisam dele na:

if (pesquisa.getCampoDois() != null) { consulta = consulta + " campoDois = :valor2"; valores.put("valor2", pesquisa.getCampoDois()); }

:smiley:

Ola novamente.
tenho uma duvida quanto ao mostrar, ou seja. Eu já inseri no banco normal, mas como eu faço para retornar esses valores. Por exemplo tenha a classe Documento e Autor nxn, quando eu vou mostrar os dados de documento quero que apareça além dos dados do documento o nome dos autores, bom qualquer coisa posto no fórum.
e minha pergunta de join ainda esta de pé
valeu

Olha eu aqui de novo espero não ter que criar nenhum tópico novo para isso

Tenho que fazer uma consulta bem grande tenho as entidades:
Documento:
codigo
titulo
tipo
ano
area(referencia area)
curso(referencia curso)
instituicao(referencia instituicao)

Area:
codigo
area

Curso:
codigo
curso

Instituicao
codigo
nome
sigla

ai eu quis fazer esse método:

[code]
public List<Documento> pesquisa(Documento documento) {
System.out.println(“inicia DAO”);
System.out.println("Titulo " + documento.getTitulo());
System.out.println(“Ano " + documento.getAno());
System.out.println(“Tipo " + documento.getTipo());
List<Documento> resultado = new ArrayList<Documento>();
Map<String, Object> valores = new HashMap<String, Object>();
String consulta = “SELECT d FROM Documento d left join fetch d.area left join fetch d.curso left join fetch d.instituicao WHERE “;
if (documento.getTitulo() != null) {
consulta = consulta + “d.titulo = :titulo”;
valores.put(“titulo”, “%” + documento.getTitulo() + “%”);
}
if (documento.getTipo() != null) {
consulta = consulta + " OR d.tipo = :tipo”;
valores.put(“tipo”, documento.getTipo());
}
if (documento.getAno() != null) {
consulta = consulta + " OR d.ano = :ano”;
valores.put(“ano”, documento.getAno());
}
if(documento.getArea() != null){
consulta = consulta + " OR d.area = :area”;
valores.put(“area”, documento.getArea());
}
if (documento.getCurso().getCurso() != null) {
consulta = consulta + " OR d.curso = :curso”;
valores.put(“curso”, documento.getCurso().getCurso());
}

    if (documento.getInstituicao().getSigla() != null) {
        consulta = consulta + " OR d.instituicao = :sigla";
        valores.put("sigla", documento.getInstituicao().getSigla());
    }
    System.out.println("a consulta: " + consulta);
    try {

        Query query = em.createQuery(consulta);

        for (Entry&lt;String, Object&gt; valor : valores.entrySet()) {
            query.setParameter(valor.getKey(), valor.getValue());
        }
        resultado = query.getResultList();

    } catch (Exception e) {
        System.out.println("erro ao realizar a consulta: " + e.getMessage());
    }
    System.out.println("fim DAO");
    return resultado;
}[/code]

mas quando eu executo da esse erro:

erro ao realizar a consulta: You have attempted to set a value of type class java.lang.String for parameter sigla with expected type of class modelo.Instituicao from query string SELECT d FROM Documento d left join fetch d.area left join fetch d.curso left join fetch d.instituicao WHERE d.titulo = :titulo OR d.tipo = :tipo OR d.ano = :ano OR d.area = :area OR d.curso = :curso OR d.instituicao = :sigla.

creio que o erro esta na minha consulta o que vocês acham?

Oi, acho que o erro é pq vc ta passando uma string mas a query ta esperando o objeto instituição, deveria ser assim:

E essa maneira de montar a query com ifs está errada. Se titulo for null vais ficar com uma query inválida ( … WHERE OR … )

Pessoal, blz !

Aqui, estou com uma duvida relacionada a consultas em JPA implementada com EclipseLink.

Tipo como listo todos objetos do BD sem usar SQL ??? estou fazendo desta forma:

@Override
	public ArrayList<Cliente> getLista() {

		EntityManager em = JpaUtil.getEntityManagerFactory()
				.createEntityManager();
		
		String consulta = "SELECT c FROM Cliente c";
		Query q = em.createQuery(consulta);
		ArrayList<Cliente> lista = new ArrayList<Cliente>(q.getResultList());
		 em.close();
		 GWT.log("servidor Listar");
		 Log.debug("Server Listar");
		return lista;
	}

Mas não queria usar nada de SQL, pois essa é uma das vantagem de utilizar um Framework ORM

Como seria isso ??? Alguém tem alguma dica aí …

eu utilizo a forma com a qual o vi-gb propôs, mas tbm tou fazendo uns testes com Criteria do JPA 2 que embora seja verbosa e chata,elimina essa concatenação de strings. Aproveitando o gancho de queries dinâmicas como vocês passam os parâmetros para esse tipo de query, eu estava utilizando a estrategia de passar todos os parametros, ex:

<input type="text" name="nome"/>
<input type="text" name="idade"/>
<input type="submit"/>

resultaria em :

mas assim a cada novo item da buscatenho adicionar um parâmetro e isso me parece gambiarra, vi
alguns exemplos que passam logo o objeto todo para a busca

<input type="text" name="pessoa.nome"/>
<input type="text" name="pessoa.idade"/>
<input type="submit"/>

e pra chamar a consulta

vocês trabalham com a primeira ou com a segunda abordagem?