Best way to use and Instantiate the EntityManagerFactory

8

My project has the following structure:

Withinthebr.mandacaru.DAOpackagearethecontrollers.ToinstantiateaJPAControllerobjectIneedaEntityManagerFactoryobjectandforthisreasonIcreatedaEntityManagerProviderclassthathasagetEntityManagerFactorymethodthatreturnsaEntityManagerFactoryobject.WheneverI'minstantiatingacontroller,IinstantiatetheEntityManagerProviderclasswithinviewtoperformanyoftheCRUDactions.Itlookslikethis:

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

    
asked by anonymous 03.01.2015 / 18:10

2 answers

6

EntityManagerFactory can and should be static:

  • In the specification says that it is multi-threaded
  • Very high cost 'for you to instantiate 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:

  • The specification says that it should not be reused
  • Ideally, open one when the request arrives and then finish.
  • If you leave it open, the resources with the database may run out
  • 05.01.2015 / 23:50
    5

    Here are the golden rules:

  • You must have EntityManager through interaction with database 1 .
  • You must have EntityManagerFactory per database in the application (persistence unit) and ClassLoader .
  • Most applications do not handle% s with% s directly and do not have to deal with 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:

  • You must have ClassLoader per database in the application (persistence unit).
  • In addition, in about 98% of cases, the application only works with a single database. And so rule number 2 can be simplified to:

  • You should have a single EntityManagerFactory in the application.
  • And this suggests that you can use the singleton design pattern:

    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 too, using EntityManagerFactory to keep references to ThreadLocal taking care not to reuse EntityManager s of different requests, which can happen if your threads are in a pool and can be reused between different requests.

    In addition, the above code is easy to modify to handle the case where there is more than one database. It is enough that each EntityManager is in a field of class EntityManagerFactory and that each is accessed by a different set of methods, or that you add a parameter to the relevant methods specifying which database is relevant.

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

        
    04.01.2015 / 06:14