Conversão parametro NamedQuery

3 respostas
D

Boa noite a todos,

Estou com um problema mas não estou conseguindo resolver…

Criei uma query com o JPQL, mas só q o EclipseLink ñ está reconhece eu acho a função nativa de conversão do postgres, essa é a query:

Para eu usar o coalesce os 2 parâmetros tem que ser iguais ,tanto p.usuario.id como :idUsuario são um long ,o problema é que o parâmetro :idUsuario não sei pq chega como String dai joga uma exceção do postgres

Dai pesquisando testei essa query no banco e rodou

Mas só que o JPA não reconhece a função CAST e joga uma exceção:

Exception Description: Syntax error parsing the query [Prova.findAll: select p from Prova p join p.listaDeQuestoes q join q.listaDePalavrasChaves pc where p.usuario.id = coalesce(CAST(:idUsuario AS bigint), p.usuario.id = 1)], line 1, column 93: unexpected token [(]. Internal Exception: NoViableAltException(83@[()* loopback of 383:9: (d= DOT right= attribute )*])

E eu estou chamando a query deste jeito:

E no DTO o atributo idUsuario é um Long

Alguém pode dar uma luz ?

3 Respostas

H

Opa, blz?

  1. Se o problema é o ID que está chegando como String, basta você converter para inteiro antes.
  2. coalesce não existe para JPQL (utilizado em namedQuery)
  3. p.usuario.id = coalesce(:idUsuario,p.usuario.id) qual a diferença do código atrás para p.usuario.id = :idUsuario
  4. Não existe cast para JPA até onde eu sei.

O que você pode fazer é

  1. Caso queira usar o coalesce você tem que usar NativeQuery
  2. Se quiser utilizar NamedQuery você terá que remover o coalesce e o cast

Se você não sabe como utilizar NativeQuery aqui tem um monte de exemplo: JPA Consultas e Dicas.

D

Bom dia ,jakefrog

Então tipo é estranho chegar como string pois estou passando direto um long ,engraçado se eu concatenar um valor na query ele aceita tipo

select p from Prova p join p.listaDeQuestoes q join q.listaDePalavrasChaves pc where p.usuario.id = COALESCE(1 ,p.usuario.id)


SELECT t2.idProva, t2.DESCRICAO, t2.NIVEL, t2.NOME, t2.PUBLICACAO, t2.idDisciplina, t2.idUsuario FROM questoes_join_pchaves t5, prova_join_questoes t4, USUARIO t3, PROVA t2, questoes t1, PALAVRASCHAVES t0 WHERE ((t3.idUsuario = COALESCE(?,t3.idUsuario )) AND (((t3.idUsuario = t2.idUsuario) AND ((t4.idProva = t2.idProva) AND (t1.idQuestaoAvulsas = t4.idQuestoes))) AND ((t5.idQuestao = t1.idQuestaoAvulsas) AND (t0.idPChaves = t5.idPChaves))))
Mas se passar um nulo já da essa exceção
Exception Description: Syntax error parsing the query [select p from Prova p join p.listaDeQuestoes q join q.listaDePalavrasChaves pc where p.usuario.id = COALESCE(null ,p.usuario.id)], line 1, column 109: unexpected token [null].
Internal Exception: NoViableAltException(54@[849:1: scalarExpression returns [Object node] : (n= simpleArithmeticExpression | n= nonArithmeticScalarExpression );])

Então essa função COALESCE é o que equivale ao ISNULL do Oracle, se meu parâmetro for nulo ele compara como todos os valores da coluna do segundo parâmetro.

Vou pesquisar sobre NativeQuery ,vlw msm

D
Só para dar uma resposta como estou atrasado, fiz um pouco porco mas está rodando eu monta a query em tempo de execução, se alguém achar alguma solução melhor eu agradeço;
@Override
	public Collection<Prova> lista(ProvaDTO dto) {

		String sql = montaQuery(dto);
		Query query = createQuery(sql, dto);

		return (Collection<Prova>) query.getResultList();
	}

	private Query createQuery(String sql, ProvaDTO dto) {

		Query query = dao.getEntityManager().createQuery(sql);

		if (sql.contains(":idUsuario"))
			query.setParameter(ID_USUARIO, dto.getIdUsuario());

		if (sql.contains(":idProva"))
			query.setParameter(ID_PROVA, dto.getIdProva());

		if (sql.contains(":idDisciplina"))
			query.setParameter(ID_DISCIPLINA, dto.getIdDisciplina());

		if (sql.contains(":nomeProva"))
			query.setParameter(NOME_PROVA, "%" + dto.getNomeProva() + "%");

		if (sql.contains(":pChaves"))
			query.setParameter(P_CHAVE, "%" + dto.getPalavraChave() + "%");

		if (sql.contains(":nivel"))
			query.setParameter(NIVEL, dto.getNivel());

		return query;
	}

	private String montaQuery(ProvaDTO dto) {
		String sql = "select p from Prova p join p.listaDeQuestoes q join q.listaDePalavrasChaves pc";
		if (dto.isUsaWhere()) {

			sql += " where";

			if (dto.getIdUsuario() != null) {

				if (sql.endsWith("where"))
					sql += " p.usuario.id = :idUsuario";
				else
					sql += " and p.usuario.id = :idUsuario";
			}

			if (dto.getIdProva() != null) {

				if (sql.endsWith("where"))
					sql += " p.id = :idProva";
				else
					sql += " and p.id = :idProva";
			}

			if (dto.getIdDisciplina() != null) {

				if (sql.endsWith("where"))
					sql += " p.disciplina.id = :idDisciplina";
				else
					sql += " and p.disciplina.id = :idDisciplina";
			}

			if (dto.getNomeProva() != null) {

				if (sql.endsWith("where"))
					sql += " p.nome like :nomeProva";
				else
					sql += " and p.nome like :nomeProva";
			}

			if (dto.getPalavraChave() != null) {

				if (sql.endsWith("where"))
					sql += " pc.palavraChave like :pChaves";
				else
					sql += " and pc.palavraChave like :pChaves";
			}

			if (dto.getNivel() != null) {

				if (sql.endsWith("where"))
					sql += " p.nivel = :nivel";
				else
					sql += " and p.nivel = :nivel";
			}
		}
		sql += " group by pc.palavraChave";
		return sql;
	}
Criado 30 de abril de 2012
Ultima resposta 1 de mai. de 2012
Respostas 3
Participantes 2