[JPA + EntityManager] Erro PersistenceException quando busco na tabela & duvida

3 respostas
A

Ola galera,

Estou com um problema quando tento procurar um projeto no meu banco, ele me da a seguinte mensagem:

Exception in thread "AWT-EventQueue-0" javax.persistence.PersistenceException: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
	at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:273)
	at test.dao.ProjetoDAO.findAllProject(ProjetoDAO.java:74)
        ...

Como estou procurando ? Usando um metodo da minha classe ProjetoDAO.class:

public List<Projeto> findAllProject() {
            return (List<Projeto>) em.createQuery("FROM Projeto p").getResultList();
      
        }

Minha DataBase.class que uso para criar o entityManager

public class DataBase{

    public EntityManager getEntityManager() {
    EntityManagerFactory factory = null;
    EntityManager entityManager = null;
    try {
       factory = Persistence.createEntityManagerFactory("teste");
       entityManager = factory.createEntityManager();
    } finally {
      factory.close();
    }
    return entityManager;
  }

}

Gostaria de saber onde esta o meu erro, ou possivelmente descutir sobre o que eu fiz de errado.

Minha duvida: 1: Toda vez que necessitar de uma pesquisa no banco, o EntityManager efetua uma conexao, até que demorada diga-se de passagem, com o banco, é possivel contornar isso utilizando algum artificio do EntityManager? Por exemplo, se tenho o codigo:
public class Exemplo {
    CasaDAO busca = new CasaDAO (); //Aqui esta o CRUD e minhas funcoes de Busca, contagem, etc
    List<Casa> casas = busca.findAllCasas(); //Quando realizo essa operacao, ha uma conexao com o banco
    ...
    //em AcitonListener de um botao de 
   botao.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              PessoaDAO buscaPessoa = new PessoaDAO();
              List<Pessoa> listPessoa = buscaPessoa.findAllPessoa(); //Realiza uma nova conexao
            }
        });
}

Se juntar todas as conexoes, daria um sistema com varias conexoes para uma unica interface (que é o meu caso), deixando assim a aplicacao mais lenta.

Creio que tenho passado a minha duvida com clareza, qualquer coisa eu tento explicar melhor.

Muito obrigado.

3 Respostas

S
Primeiro você esta realizando uma query sem select "FROM Projeto p",use "Select p FROM Projeto p".
public List<Projeto> findAllProject() {
            return (List<Projeto>) em.createQuery("Select p FROM Projeto p").getResultList();
}
Segundo ao criar o EntityManager você esta fechando o EntityManagerFactory logo em seguida, quando se fecha o factory todos os manger gerados por ele são fechados. Tente isso:
public class DataBase{

    public EntityManager getEntityManager() {
    EntityManagerFactory factory = null;
    EntityManager entityManager = null;
    factory = Persistence.createEntityManagerFactory("teste");
    entityManager = factory.createEntityManager();
   return entityManager;
  }

}
D

Porque não usar um container que vc possa injetar o EntityManager tipo JBOSS seria bem mais fácil de trabalhar.
mas se for exigência.

@PersistenceContext
	private EntityManager em;
F

Sobre o erro não sei dizer. Verifique todas as dependências do Hibernate.

Sobre a dúvida e a lentidão. Criar um EntityManagerFactory é caro e demora um pouco mesmo. Ele verifica todo o seu mapeamento, sempre faz update ou create-drop dependendo das suas configurações. Logo você só deve fazer isso uma vez ao iniciar a aplicação. Apenas o EntityManager que representa uma conexão é criado e fechado várias vezes. Você pode (e deve) usar um pool de conexões com c3p0 por exemplo para não ter que abrir e fechar todas as vezes, mas não me preocuparia com isso agora.

Sua classe poderia ser algo como:

public class DataBase{  

    private static final EntityManagerFactory factory;
    private static Logger logger = Logger.getLogger(DataBase.class);

    static {
        try {
            factory = Persistence.createEntityManagerFactory("teste");
        } catch (Throwable ex) {
            throw new RuntimeException(ex);
            logger.error("Initial EntityManagerFactory creation failed", ex);
        }
    }

    public EntityManager getEntityManager() {  
       return factory.createEntityManager();  
  }  
  
}

Você também deve fechar a conexão (entityManager) ao terminar sua operação.

entityManager.close();
Criado 2 de abril de 2013
Ultima resposta 9 de abr. de 2013
Respostas 3
Participantes 4