Problema com JPA - EntityManager

Olá Pessoal tudo bem? Bom estou com um problema com o meu JPA aparentemente qualquer tentativa de salvar um objeto ele não funciona basicamente java.lang.NullPointerException


MEU DAO GENERICO:

public class GenericoDAO<T extends Entidade> {
@PersistenceUnit(unitName="MeusistemaPU")
   EntityManagerFactory factory;

public EntityManager getEM() throws InstantiationException, IllegalAccessException{
    return factory.createEntityManager();
}

public T salvar (T t) throws Exception{
    EntityManager em = getEM();
    
    
    try{
        em.getTransaction().begin();
      
        if(t.getId() == null){
        
            em.persist(t);
        }else{
            if(!em.contains(t)){           	
                if(em.find(t.getClass(),t.getId()) == null){
                    throw new Exception("Erro ao atualizar");
                }
            }
            t = em.merge(t);
        }
        em.getTransaction().commit();
    }finally{
        em.close();
    }
    return t;
}

}


Minha Interface Entidade:

public interface Entidade {

   public Integer getId();

}

Minha Classe de Teste

    public class AnimalTeste {

      public static void main(String[] args) throws Exception {
	Animal gato = new Animal();

    GenericoDAO gn = new GenericoDAO();
    
    gato.setDataNascimento("12-02-2013");
    gato.setNomeAnimal("Felix");
    gato.setPelagem("Preta");
    gato.setPeso(4.35);

    System.out.println(gato.toString());
    //Neste momento no gn.salvar ele nem entra e já lança a Exception 
    gn.salvar(gato);

}

}


Meu Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
 <persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="MeusistemaPU" transaction-type="RESOURCE_LOCAL">
	<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
	
	<class>com.entidade.Animal</class>
	
	<properties>
		<property name="eclipselink.jdbc.batch-writing" value="JDBC" />

		<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
		<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/animais" />
		<property name="javax.persistence.jdbc.user" value="root" />
		<property name="javax.persistence.jdbc.password" value="1234" />
		<property name="eclipselink.target-database" value="MySQL"/>
	</properties>
</persistence-unit>
</persistence>

Aqui o Erro que da

 Exception in thread "main" java.lang.NullPointerException
at com.DAO.GenericoDAO.getEM(GenericoDAO.java:16)
at com.DAO.GenericoDAO.salvar(GenericoDAO.java:20)
at com.teste.AnimalTeste.main(AnimalTeste.java:28)

Pelo o que pude ver acredito que seu código não está conseguindo recuperar a instância do objeto no momento em que você faz getEM();
bem no trecho abaixo:

public T salvar (T t) throws Exception{
    EntityManager em = getEM(); //Ponto em que a instância não foi recuperada

Faça um debug no código pra ver por que não está recuperando.

Remove o :

em.getTransaction().commit();

E tenta salvar agora…

Eu removi, porem mesmo com o em.getTransaction… Meu AnimalTeste(main) não chega nem a chamar o metodo salvar da classe GenericoDAO

O Debug ele termina em:

public EntityManager getEM() throws InstantiationException, IllegalAccessException{
   
    return factory.createEntityManager(); //Neste trecho está Null
}

Fiz um teste no meu GenericoDAO comentando tudo e deixando apenas um toString no metodo Salvar o Objeto está sendo passado normalmente

Tenta criar a fabrica manualmente e veja o que acontece!

private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("MeusistemaPU");

ps: arranca ela do GenericDao e coloca em uma JpaUtil, por exemplo.
ps2: acho interessante que tenha vários DAO’s que estendam GenericDao, passando a classe no diamond

1 curtida

O Erro agora é:

Exception in thread "main" java.lang.ExceptionInInitializerError
at com.teste.AnimalTeste.main(AnimalTeste.java:12)
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named MeusistemaPU
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:84)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)

Acredito que seu erro foi criado por falta de atenção com o nome da sua unidade de persistência.

Seu projeto tem um arquivo de configuração chamado persistence.xml, nele você encontrará o nome da sua unidade de persistência. A linha do arquivo é essa:

`<persistence-unit name="AppJSFPU" transaction-type="RESOURCE_LOCAL">`

Por padrão o nome criado automaticamente é o nome do seu projeto no exemplo acima AppJSF + PU de Persistence Unit.

Recomendo além do DAO genérico, você implementar uma classe para criar o EntityManager. Crie esta classe no pacote DAO assim (é uma classe Java normal só por desencargo de consciência kkkkkk):

public class PersistenceUtil {

private static EntityManagerFactory emf = null;

private PersistenceUtil() {
}

public static EntityManager getEntityManager() {
    if (emf == null) {
        emf = Persistence.createEntityManagerFactory("AppJSFPU");
    }
    return emf.createEntityManager();
}

public static void close(EntityManager em) {
    if (em != null) {
        em.close();
    }
}

}

Seu DAO genérico pode ficar assim:

public class DaoGenerico implements Serializable {

private static DaoGenerico instance = new DaoGenerico();
private EntityManagerFactory emf = null;

public static DaoGenerico getInstance() {
    return instance;
}

private DaoGenerico() {
}

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

public void save(Object objeto) {
    EntityManager em = null;
    try {
        em = PersistenceUtil.getEntityManager();
        em.getTransaction().begin();
        em.persist(objeto);
        em.getTransaction().commit();
    } catch (Exception ex) {
    } finally {
        if (em != null) {
            em.close();
        }
    }
}

public void update(Object objetoAtualizado) {
    EntityManager em = null;
    try {
        em = PersistenceUtil.getEntityManager();
        em.getTransaction().begin();
        em.merge(objetoAtualizado);
        em.getTransaction().commit();
    } catch (Exception ex) {
        System.out.println("Erro:" + ex.getMessage());
    } finally {
        if (em != null) {
            em.close();
        }
    }
}

public void delete(Object objeto) {
    EntityManager em = null;
    try {
        em = PersistenceUtil.getEntityManager();
        em.getTransaction().begin();
        Object objetoDeletar = em.merge(objeto);
        em.remove(objetoDeletar);
        em.getTransaction().commit();
    } catch (Exception ex) {
    } finally {
        if (em != null) {
            em.close();
        }
    }
}

}

Notas:

  • O DAO genérico acima esta chamando o método getEntityManager da classe PersistenceUtil, caso você queira continuar usando a sua classe DAO acrescente a chamada a esse método lá.

  • Não se esqueça de trocar o nome da unidade de persistência na classe PersistenceUtil.
    emf = Persistence.createEntityManagerFactory(“AppJSFPU”);

  • A classe PersistenceUtil e o DAO genérico do exemplo utilizam um padrão de projeto chamado singleton, caso queira dar uma lida para saber mais recomendo:
    Devmedia-Trabalhando com singleton

Problema Resolvido, troquei a versão do Jar do Hibernate para a 4.2.8 funcionou perfeitamente.