JPA: método close() de EntityManager, quando usar?

7 respostas
F

Criei um DAO genérico que é acessado pelos DAOs das minhas classes de entidade.

Conforme mostrado nesse link, usei uma instância nova do EntityManager para cada consulta ou alteração no bd. O problema é que ao usar many to many com fetch type lazy ocorre uma exceção ao tentar obter a coleção, pois o EntityManager já foi fechado.

Exemplo:

Order order = null;
try{
        order = em.find(Order.class, orderId);
    }finally{
        em.close();
    }

// Gera exceção porque o EntityManager foi fechado
List<Item> itens = order.getItemCollection();

Segue um dos métodos que uso. Se eu comentar em.close() funciona corretamente

public static List getResultList(String namedQuery)
   throws SPDNoResultException 
   {
      EntityManager em = getEntityManager();
      try
      {       
         List resultList = em.createNamedQuery(namedQuery).getResultList();
         if(resultList.isEmpty())
         {
            throw new SPDNoResultException();
         }
         return resultList;
      }
      finally
      {
         em.close();
      }                  
   }

7 Respostas

J

Dê uma pesquisada sobre OpenSessionInView que irá te ajudar.

Na ultima revista Mundo Java, saiu um artigo legal sobre ele.

F

Olhei o artigo no site do Hibernate, mas estou usando Java SE. Tem alguma solução para essa plataforma?

R

Você tá fechando a conexão com o banco de dados, por isso tá dando erro, o que na verdade você tem que buscar é como controlar melhor sua sessão com o bd para realizar suas operações com ele, enquanto você não terminar suas interações não pode fechar sua conexão.

ps. pesquise a documentação do JPA para entender melhor o que é EntityManager e etc. vai dando uma navegada em: http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html ou mesmo no: http://www.hibernate.org/hib_docs/entitymanager/reference/en/html/

espero que ajude, de qualquer forma entre no site da Caelum e veja alguma video aula sobre JPA mostrando um exemplo com Hibernate e TopLink, esse exemplo é para mostrar como a especificação JPA é atendida pelas duas implementação, mas pode te dar um horizonte por ter um exemplo disso com Java SE.

F

Assisti o vídeo, mas ainda não ficou claro, pois o exemplo mostrado é simples.

R

:shock:

mas começamos na simplicidade, concorda?

veja esse how-to agora: http://www.oracle.com/technology/products/ias/toplink/jpa/howto/java-se-usage.html

espero que ajude mais.

D

Fkj o que acontece é que você está dando responsabilidade de mais para seu DAO, o dao não tem a responsabilidade de devolver recursos (fechar o entity manager), ele apenas acessa os dados da sua fonte de dados.

O seu DAO não o permitiria por exemplo fazer transações (seu DAO tambem não tem responsabilidade de controlar transações)

você podia mudar seu dao para ele receber o Entity manager no construtor e quem chama ele ficar responsavel por devolver os recursos, enviar transações, dar rollback, etc.

F

Obrigado pelas dicas. Segue abaixo como o código ficou, o que acham?

DAO genérico

package br.com.spdata.jpa;

import br.com.spdata.exceptions.SPDNoResultException;
import br.com.spdata.exceptions.SPDPersistenceException;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import org.hibernate.validator.InvalidStateException;

public class SPDJPA
{   
   private static SPDJPA               instance;
   private static String               persistenceUnit;
   private static EntityManagerFactory entityManagerFactory;

   private SPDJPA()
   {
   }

   public static synchronized SPDJPA getInstance()
   {
      if(instance == null) 
      {
         instance = new SPDJPA();       
      }
      return instance;
   }

   @Override
   protected Object clone() throws CloneNotSupportedException
   {
      throw new CloneNotSupportedException();
   }      
   
   public static void connect(String persistenceUnit, Map properties) throws SPDPersistenceException
   {     
      try
      {
         SPDJPA.persistenceUnit = persistenceUnit;
         entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit, properties);
      } 
      catch(PersistenceException e)
      {
         throw new SPDPersistenceException(e.getMessage());
      }
      finally
      {
         if(entityManagerFactory != null)
         {
            entityManagerFactory.close();
         }
      }
   }
   
   public static void connect(String persistenceUnit) throws SPDPersistenceException
   {
      connect(persistenceUnit, null);
   }       
   
   public static boolean isConnected()
   {
      return (entityManagerFactory != null);      
   }
      
   public static void close(EntityManager em)
   {
      if(em != null)
      {
         em.close();
      }
   }
   
   public static EntityManager getEntityManager()
   {
      return entityManagerFactory.createEntityManager();
   }    
   
   public static String getPersistenceUnit() 
   {
      return persistenceUnit;
   }      
   
   public static void persist(EntityManager em, Object entity) throws InvalidStateException, SPDPersistenceException
   {      
      try
      {         
         em.getTransaction().begin();
         em.persist(entity);
         em.getTransaction().commit();
      } 
      catch(InvalidStateException e)
      {
         throw e;
      }
      catch(Exception e) 
      {
         if(em.getTransaction().isActive())
         {
            em.getTransaction().rollback();
         }
         throw new SPDPersistenceException(e.getLocalizedMessage());  
      }
   }   
   
   public static void remove(EntityManager em, Object entity) throws SPDPersistenceException
   {
      try
      {         
         em.getTransaction().begin();
         em.remove(entity);
         em.getTransaction().commit();
      }      
      catch(Exception e) 
      {
         em.getTransaction().rollback();
         throw new SPDPersistenceException(e.getLocalizedMessage());  
      }      
   }
   
   public static <T> T getById(EntityManager em, Class<T> entityClass, Object primaryKey)
   throws SPDNoResultException {
      T t = em.find(entityClass, primaryKey);
      if(t == null)
      {
         throw new SPDNoResultException();
      }
      return t;      
   }    
   
   private static Query createParameterizedNamedQuery(EntityManager em, String namedQuery, SPDQueryParameters queryParameters)
   {
      Query query = em.createNamedQuery(namedQuery);
      Enumeration keys = queryParameters.keys();
      while(keys.hasMoreElements())
      {
         String key = (String)keys.nextElement();
         query.setParameter(key, queryParameters.get(key));
      }                       
      return query;
   }
   
   @SuppressWarnings("unchecked")
   public static <T> T getSingleResult(EntityManager em, String namedQuery)
   throws SPDNoResultException 
   {
      T t;
      try
      {
         t = (T)em.createNamedQuery(namedQuery).getSingleResult();  
         if(t == null)
         {
            throw new SPDNoResultException();            
         }
      }
      catch(NoResultException e)
      {
         throw new SPDNoResultException();
      }
      return t;
   }   
      
   @SuppressWarnings("unchecked")
   public static <T> T getSingleResult(EntityManager em, String namedQuery, SPDQueryParameters queryParameters) throws SPDNoResultException
   {       
      Query query = createParameterizedNamedQuery(em, namedQuery, queryParameters);
      T t;
      try
      {
         t = (T)query.getSingleResult();  
         if(t == null)
         {
            throw new SPDNoResultException();            
         }
      }
      catch(NoResultException e)
      {
         throw new SPDNoResultException();
      }
      return t;
   }      
 
   public static List getResultList(EntityManager em, String namedQuery)
   throws SPDNoResultException 
   {
      List resultList = em.createNamedQuery(namedQuery).getResultList();
      if(resultList.isEmpty())
      {
         throw new SPDNoResultException();
      }
      return resultList;      
   }  
   
   public static List getResultList(EntityManager em, String namedQuery, SPDQueryParameters queryParameters) 
   throws SPDNoResultException
   {
      Query query = createParameterizedNamedQuery(em, namedQuery, queryParameters);
      List resultList = query.getResultList();
      if(resultList.isEmpty())
      {
         throw new SPDNoResultException();
      }
      return resultList;
   }   
}

DAO de uma entidade

package br.com.spdata.orm.spdata.dao;

import br.com.spdata.exceptions.SPDNoResultException;
import br.com.spdata.jpa.SPDJPA;
import br.com.spdata.jpa.SPDPersistenceDAO;
import br.com.spdata.orm.spdata.Sctecnic;
import java.util.List;
import javax.persistence.EntityManager;

public class SctecnicDAO
{   
   private static SctecnicDAO instance;

   private SctecnicDAO()
   {
   }

   public static synchronized SctecnicDAO getInstance()
   {
      if(instance == null) 
      {
         instance = new SctecnicDAO();       
      }
      return instance;
   }

   @Override
   protected Object clone() throws CloneNotSupportedException
   {
      throw new CloneNotSupportedException();
   }   
 
	public static Sctecnic getById(EntityManager em, short codigoTecnico) throws SPDNoResultException
   {
		return SPDJPA.getById(em, Sctecnic.class, codigoTecnico);
   }
    
   public static List<Sctecnic> getImplantadores(EntityManager em) throws SPDNoResultException
   {
   	return SPDJPA.getResultList(em, "Sctecnic.getImplantadores");
   }    
}
Criado 23 de outubro de 2007
Ultima resposta 28 de nov. de 2007
Respostas 7
Participantes 4