Best Way to Use and Instantiate Entitymanagerfactory

Asked

Viewed 2,937 times

8

My project has the following structure:

pacotes do projeto

Within the package br.mandacaru.DAO are the controllers. To instantiate an object JPAController I need an object EntityManagerFactory and for that reason I created a class EntityManagerProvider which has a method getEntityManagerFactory that returns an object EntityManagerFactory. Whenever I’m instantiating one controller, instancio the class EntityManagerProvider within the view to perform any of the CRUD actions. Staying as follows:

Insert

It turns out that way, for each View i will need to instantiate in the class the object EntityManagerFactory which according to what the project is growing will become expensive and I think not very efficient. What would be the best way to instantiate this object EntityManagerFactory in the main class and pass it to the views?

  • 1

    My suggestion for this case is to use the default Singleton. If the class EntityManagerProvider for its facade, it is easier to implement the Singleton in it. Otherwise you will have to create a class to implement this standard.

  • @Wakim The Entitymanagerprovider class I created myself and am seeing about Singleton now. It really might be the solution. I will test.

  • For use, I would create a solution to Inject the Entitymanager where necessary. In simpler systems it is totally unnecessary, but for more complex applications it helps to decouple the system from a specific class, the code gets a little cleaner and the chances of errors occurring at runtime is less, since the objects or proxies are injected before the method begins to perform. Outside of an application server it is easy to achieve this using Spring, for example, but you can also use CDI using Weld.

2 answers

6


Entitymanagerfactory can and should be static:

  1. The specification says it’s multi-threaded
  2. Cost 'too loud' for you to instill it all the time

In the class you created, leave the Entitymanagerfactory as private static EntityManagerFactory emf. Then create a static method like:

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

Entitymanager is not thread safe:

  1. The specification says it should not be reused
  2. Ideally, open one when the request arrives and then finish.
  3. If you leave it open, resources with the database may run out

5

Here are the golden rules:

  1. You must have a EntityManager by interaction with the database1.
  2. You must have a EntityManagerFactory by database in the application (persistence Unit) and for ClassLoader.

Most applications do not deal with ClassLoaders directly and does not need to handle multiple versions of the same class in memory at the same time. Therefore in 99.9% of cases, rule number 2 can be simplified to:

  1. You must have a EntityManagerFactory by database in the application (persistence Unit).

Also, in about 98% of cases, the application only works with a single database. And therefore, rule number 2 can be simplified to:

  1. You must have a single EntityManagerFactory in the application.

And this suggests that you can use the design pattern Singleton:

public final class EntityManagerProvider {

    private static final EntityManagerProvider INSTANCE = new EntityManagerProvider();

    private final EntityManagerFactory factory;

    private EntityManagerProvider() {
        this.factory = Persistence.createEntityManagerFactory("SUA_BASE_DE_DADOS");
    }

    public static EntityManagerProvider getInstance() {
        return INSTANCE;
    }

    public EntityManagerFactory getFactory() {
        return factory;
    }

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

This class above takes care of rule 2 perfectly. I suggest you implement rule number 1 in it as well, using a ThreadLocal to maintain references to EntityManagers and taking care not to reuse EntityManagerdifferent requests, which can happen if your threads are in a pool and can be reused between different requests.

Also, the above code is easy to be modified to handle the case where there is more than one database. Just that each EntityManagerFactory is in a class field EntityManagerProvider and that each one is accessed by a different set of methods, or that you add a parameter to the relevant methods specifying which is the relevant database.


1 - In this context, a sequence of operations related to running consecutively in the database is defined by interaction with the database, possibly in a single transaction scope.

  • One Entitymanager per session? You could pass me the material from where you based this practice?

  • @uaiHebert I changed the term to request and I defined it better, to avoid confusion.

  • Still your request notice sounds strange. If I have 2 processing, I should then use two entityManager?

  • @uaiHebert Depends. Anyway maybe I’m not expressing myself right. The focus of the text is the EntityManagerFactory, then I didn’t want to put more than a short text of just a sentence on the EntityManager. Any suggestions to improve the text?

Browser other questions tagged

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