[Resolvido] Não está setando o valor na query.setParameter ao tentar fazer uma consulta no banco

Estou com um problema na hora de setar um valor na query.setParameter. Uso EcliseLink e MySQL, fiz uma consulta sem setar parâmetros e funcionou, o que será que pode ser?

Classe onde tento fazer a consulta:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.redew.dao;

import br.com.redew.entidade.Funcionario;
import java.io.Serializable;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 *
 * @author Desenvolvimento
 */
public class FuncionarioDao extends GenericoDao<Funcionario, Integer> implements Serializable {

    public Funcionario autenticar(Funcionario funcionario) throws NoResultException, NonUniqueResultException {
        Query query = getEm().createNamedQuery("Funcionario.autenticar");
        query.setParameter("email", funcionario.getEmail());
        query.setParameter("senha", funcionario.getSenha());
        return (Funcionario) query.getSingleResult();
    }
}

Classe GenericoDao onde abro a conexão:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.redew.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 *
 * @author weder
 */
public class GenericoDao<T, ID> implements Serializable {

    private EntityManagerFactory emf;
    private EntityManager em;
    private Class<T> classe;

    public GenericoDao() {
        emf = Persistence.createEntityManagerFactory("br.com.redew_redew_war_1.0.0PU");
        em = emf.createEntityManager();
        classe = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public T find(ID id) {
        return getEm().find(classe, id);
    }

    public Object insert(T Objeto) {
        getEm().getTransaction().begin();
        getEm().persist(Objeto);
        getEm().flush();
        getEm().getTransaction().commit();
        return Objeto;
    }

    public Object update(T Objeto) {
        getEm().getTransaction().begin();
        getEm().merge(Objeto);
        getEm().flush();
        getEm().getTransaction().commit();
        return Objeto;
    }

    public Object delete(T Objeto) {
        getEm().getTransaction().begin();
        getEm().remove(Objeto);
        getEm().flush();
        getEm().getTransaction().commit();
        return Objeto;
    }

    public List callNamedQuery(String namedQuery) {
        Query q = getEm().createNamedQuery(namedQuery);
        return q.getResultList();
    }

    public List callNativeNamedQuery(String query) {
        Query q = getEm().createNativeQuery(query);
        return q.getResultList();
    }

    public EntityManager getEm() {
        return em;
    }
}

Dá esse erro ao tentar passar algum valor no setParameter sem passar nenhum valor ele funciona:

Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.1.v20150605-31e8258): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed. Error Code: 0 Call: SELECT id, email, nome, senha, telefone, id_empresa FROM funcionario WHERE ((email = ?) AND (senha = ?)) bind => [2 parameters bound] Query: ReadAllQuery(name=“Funcionario.autenticar” referenceClass=Funcionario sql=“SELECT id, email, nome, senha, telefone, id_empresa FROM funcionario WHERE ((email = ?) AND (senha = ?))”)

Me ajudem ai por favor kk

Bom dia,
não é questão de setParameter, sua conexão está fechada.
Essa conexão fica aberta por muito tempo ou vc abre ela antes deste código?

Bom dia amigo,

Então eu abro antes a conexão, eu fiz uma consulta buscando tudo e funcionou, ao tentar passar um valor no setParameter ele não seta, tem alguma ideia desse erro?.

Baseado em que vc afirma que não seta o valor?

O erro:
MySQLNonTransientConnectionException: No operations allowed after connection closed.
É de conexão fechada.
Caso vc mantem esta conexao aberta por muito tempo, é importante saber que o MySQL tem timeout e fecha as conexões automaticamente após algum tempo.

Fiz uma busca sem setParameter e funcionou.

public List<Funcionario> findAll() {
    Query q = getEm().createNamedQuery("Funcionario.findAll");
    return q.getResultList();
}

Query na entidade:

@NamedQuery(name = “Funcionario.findAll”, query = “SELECT f FROM Funcionario f”)

No erro os valores das variáveis onde tento dar um setParameter fica com um “?”.

Error Code: 0 Call: SELECT id, email, nome, senha, telefone, id_empresa FROM funcionario WHERE ((email = ?) AND (senha = ?)) bind => [2 parameters bound]

No erro sempre vai aparecer com ? porque ele não faz uma simples substituição. É literalmente passado como parametro AO BANCO.

Entendi, mas só não entendo por que no findAll ele funcionou, e ao tentar passar um setParameter dar esse erro.

Query que dar erro ao tentar dar um set nas variáveis:

@NamedQuery(name = “Funcionario.autenticar”, query = “SELECT f FROM Funcionario f WHERE f.email = :email AND f.senha = :senha”)

Realmente também não consigo fazer uma ligação entre este erro ao passar parametro.
Tente criar uma conexao nova antes desta consulta, só pra testar.

Uma ressalva sobre outra coisa:
query.getSingleResult()

Teoricamente o singleResult é o mais indicado para se obter só um resultado. MAS se atente ao fato de que se não retornar 1 resultado na consulta, vai estourar uma exceção e isso precisa ser tratado em algum lugar ou vai dar crash ao tentar logar com senha errada por exemplo.

Vou tentar aqui e já dou a resposta kk

Sobre o query.getSingleResult() no banco eu deixo o email como UNIQUE então teoricamente não tem como retornar mais de 1 resultado né?

Tem sim, pq vc pesquisa por email = x e senha = x
Se o cara digitar a senha diferente da dele, a consulta não vai encontrar o registro do Funcionario ai estoura o problema.
Tem duas formas de tratar:
1 - tratando a exceção NoResultException
2 - Outra seria usar o getResultList e retornar o primeiro valor da lista caso tenha itens ou null se ela for vazia.

Eu uso desta segunda forma.

1 curtida

Verdade nunca pensei desse jeito obrigado cara,

A questão sobre retornar o query.getResultList funcionou passando setParameter ficou assim:

public List<Funcionario> autenticar(Funcionario funcionario) {
    Query query = getEm().createNamedQuery("Funcionario.autenticar");
    query.setParameter("email", funcionario.getEmail());
    query.setParameter("senha", funcionario.getSenha());
    return query.getResultList();
}

Sou seu fã cara kkkk funcionou.

1 curtida