Close entityManager after operations? How to manage?

Asked

Viewed 928 times

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, certain doubts arise.

For example, before any operation with the database you need to start the Entitymanager operation and commit after the execution of the operation.

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

1st question : You must close 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? how? through entityManager.close() ?

2º Doubt : Each DAO method must 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();
}

3º Doubt (COUPLING) : How to pass the Entitymanager more efficiently to the DAO layer?

The examples I had access to worked with a DAO layer that did database operations, however, these DAO’s received an instance from Entitymanager via constructor.

Something like :

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

But this confuses me when working with this implementation format when I’m developing my pages with JSF, because I end up creating a coupling that I don’t know how to deal with. For example, I feel the need to recover an instance of Entitymanager 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 incongruous to the class context, since the right thing would be to have all the tools, persistence objects and methods in the classes that are reserved for the purpose of conducting transactions in databases.

To illustrate my doubt:

@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 will need multiple instances of Entitymanager and this seems wrong. Some solution for how to work the transition from entityManager to my DAO layer ?

2 answers

2


Things you learn after you hit your head:

1) Try to use only one jpa variable during every run.

2) Close the connection at the end.

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

How does it look in the code?

On DAO - you can use a generic that is extended by others to prevent replication:

EntityManagerFactory factory;
EntityManager manager;

At the beginning of the dao:

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

In case of exception:

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

To be executed on completion, after executing all necessary operations:

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

In Controller or who to call dao:

private NomeentidadeDAO dao = null;

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

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 make an exception:

    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

1

Assuming it is a web application, follow my considerations:

  1. A context per request: With each request made to your application, create only 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.
  2. Clean entities: Your domain entities should not have any dependencies. Your comment was pertinent as in a list of EnderecoBean you would have several instances of your Entitymanager, and that’s not what we want. Entities should only have properties, behaviors, and the ability to validate themselves. See my github, there are examples of self-validated entities, are in C#, but the principle is the same.
  3. Application manages transaction: It is not your DAO layer that will manage the transaction. It only executes what you are asked to: create a record, update, delete or select. But an action, a command that your application needs to do, often requires multiple requests to the DAO. Ex: Creating a new registration can mean entering data into multiple records, such as person, address, login, all in a single transaction, which should only commit at the end of the execution of any command. Look at this method, he makes several executions before deciding to commit or rollback.

I will not go deeper than that, otherwise it will become a very long answer, but I believe that I can already help clarify some ideas.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.