Close the entityManager after operations? How to manage?

3

I have been doing some courses and all the material I have read so far exemplifies the use of JPA / Hibernate in small examples, however, when we are developing something more concrete as a project, some questions arise.

For example, before any operation with the database, you must start the EntityManager operation and commit after the operation.

entityManager.getTransaction().begin();
entityManager.persist(Estado);
entityManager.getTransaction().commit();

1st Doubt: Do I need to close the EntityManager at some point? In this case, I initiated a transaction before performing my operations: "entityManager.getTransaction (). begin ()". Should I terminate this transaction in any way? as? through the entityManager.close ()?

2nd Doubt: Should each DAO method start and commit the transaction?

public void inserir(Cidade cidade){
    entityManager.getTransaction().begin();
    entityManager.persist(cidade);
    entityManager.getTransaction().commit();
}

public void remover(Cidade cidade){
    entityManager.getTransaction().begin();
    entityManager.remove(cidade);
    entityManager.getTransaction().commit();
}

3rd QUESTION: How to pass the EntityManager more efficiently to the DAO layer?

The examples I had access worked with a DAO layer that did the database operations, however, these DAO's were given an EntityManager instance via the constructor.

Something like:

public class CidadeDAO implements DAOInterface<Cidade>{
   private EntityManager em;
   public CidadeDAO(EntityManager em){
      this.em = em; 
   }
}

But this ends up confusing me when working with this implementation format when I'm developing my pages with JSF, because I end up creating a coupling that I do not know how to handle. For example, I feel the need to retrieve an EntityManager instance in each @ManagedBean to be able to inject my DAO's, and consequently makes me declare an entityManager within ManagedBean and I think this is incongruent to the context of the class , since it would be the right thing to have all the tools, objects and methods of persistence in the classes that are reserved in order to perform transactions in databases.

To illustrate my question:

@ManagedBean
public class EnderecoBean{
     private EntityManager em;

     public EnderecoBean(){
         this.em = JPAUtil.getEntityManager();
     }

     public void operacaoExemplo(){
         EstadoDAO dao = new EstadoDAO(em);
         List<Cidade> listaCidades = dao.listar();
     }
}

I find this strange, because if I have multiple DAO's I'm going to need multiple instances of EntityManager and this seems wrong to me. Any solution on how to work the entityManager pass for my DAO layer?

    
asked by anonymous 29.03.2017 / 03:39

2 answers

2

Things we learn after hitting our head:

1) Try to use only one jpa variable during execution.

2) Close the connection at the end.

3) If something goes wrong, give a rollback, close the connection and not reuse the entity manager object, generate another.

How is this in the code?

In DAO - you can use a generic that is extended by others to avoid replication:

EntityManagerFactory factory;
EntityManager manager;

At the beginning of the day:

factory = Persistence.createEntityManagerFactory("persistenceunit");
manager = factory.createEntityManager();    
manager.getTransaction().begin();    

In case of an exception:

manager.getTransaction().rollback();
manager.close();
factory.close();

To run on completion, after performing all necessary operations:

manager.getTransaction().commit();
manager.close();
factory.close();    

On Controller or who to call dao:

private NomeentidadeDAO dao = null;

You can use a singleton to take advantage of the same entity damage:

private void getDAO()
{
    if(dao==null)
    {
        dao = new NomeentidadeDAO();
    }
}

At the end of the run to close:

if(dao!=null) 
{ 
    dao.end(); 
    // sendo q esse dao.end executa aquele trecho que encerrra a conexão
}

If you give any exceptions:

    dao.rollbackandclose();  
    // sendo q esse dao.rollbackandclose executa aquele trecho em caso de exceção, visto acima

    dao=null;  // nulifica a variável pra essa não ser reaproveitada (no caso do Hibernate isto é inclusive recomendação)
    // caso precise depois chama o singleton pra gerar outra
    
29.03.2017 / 11:40
1

Assuming that it should be a web application, it follows my considerations:

  • One context per request : For each request made to your application, just create a repository context. In your case, open the connection once and start the transaction. And close the connection at the end of the request, before your return.
  • Clean Entities : Your domain entities should have no dependencies at all. Your comment was relevant because in a list of EnderecoBean you would have multiple instances of your EntityManager, and that's not what we want. Entities should only possess properties, behaviors, and ability to self-validate. See my github, have examples of auto-validated entities , are in C# , but the principle is the same.
  • Application manages transaction : It is not your DAO layer that will manage the transaction. It only performs what you are asked to do: create a record, update, delete, or select. But an action, a command that your application needs to do, often requires multiple requests to DAO. Ex: Creating a new register can mean entering data in multiple records, such as person, address, login, all in a single transaction, which should only be comed at the end of every command execution. View this method , it does several runs before deciding on commit or rollback .
  • I will not delve more deeply into this, otherwise it will become a very long answer, but I believe it can help to clarify some ideas.

        
    29.03.2017 / 09:17