Когда должен быть создан / открыт экземпляр EntityManagerFactory? - PullRequest
24 голосов
/ 28 декабря 2010

Хорошо, я прочитал кучу статей / примеров, как написать Entity Manager Factory в синглтоне.

Один из них мне легче всего понять:

http://javanotepad.blogspot.com/2007/05/jpa-entitymanagerfactory-in-web.html

Я узнал, что EntityManagerFactory (EMF) должен создаваться только один раз, предпочтительно в области приложения.

А также обязательно закройте ЭДС, как только она будет использована (?)

Итак, я написал вспомогательный класс EMF для бизнес-методов:

public class EmProvider {

    private static final String DB_PU = "KogaAlphaPU";

    public static final boolean DEBUG = true;

    private static final EmProvider singleton = new EmProvider();

    private EntityManagerFactory emf;

    private EmProvider() {}

    public static EmProvider getInstance() {
        return singleton;
    }


    public EntityManagerFactory getEntityManagerFactory() {
        if(emf == null) {
            emf = Persistence.createEntityManagerFactory(DB_PU);
        }
        if(DEBUG) {
            System.out.println("factory created on: " + new Date());
        }
        return emf;
    }

    public void closeEmf() {
        if(emf.isOpen() || emf != null) {
            emf.close();
        }
        emf = null;
        if(DEBUG) {
            System.out.println("EMF closed at: " + new Date());
        }
    }

}//end class

И мой метод с использованием EmProvider:

public String foo() {
    EntityManager em = null;
    List<Object[]> out = null;
    try {

        em = EmProvider.getInstance().getEntityManagerFactory().createEntityManager();
        Query query = em.createNativeQuery(JPQL_JOIN); //just some random query 
        out = query.getResultList();
    }
    catch(Exception e) {
        //handle error....
    }
    finally {
        if(em != null) {
             em.close(); //make sure to close EntityManager
        }
        //should I not close the EMF itself here?????
        EmProvider.getInstance().closeEmf();
    }

Я сделал все возможное, чтобы закрыть EntityManager (em) на уровне метода, как это было предложено. Но когда тогда должен быть закрыт EntityManagerFactory? И почему EMF должен быть настолько одиночным ??? Я читал о проблемах параллелизма, но так как я не опытный многопоточный грамматик, я не совсем понимаю эту идею.

1 Ответ

57 голосов
/ 28 декабря 2010
  • Экземпляры EntityManagerFactory являются тяжеловесными объектами.Каждая фабрика может поддерживать кэш метаданных, кэш состояния объекта, пул EntityManager, пул соединений и многое другое.Если вашему приложению больше не требуется EntityManagerFactory, вы должны закрыть его, чтобы освободить эти ресурсы.

  • Когда EntityManagerFactory закрывается, все EntityManager из этой фабрики и, соответственно, все сущности, управляемые этими EntityManagers, стать недействительным.

  • Гораздо лучше держать фабрику открытой в течение длительного периода времени, чем многократно создавать и закрывать новые фабрики.Таким образом, большинство приложений никогда не закроет фабрику или закроет ее только при выходе из приложения.

  • Только приложения, которым требуется несколько фабрик с различными конфигурациями, имеют очевидную причину для создания и закрытия нескольких приложений.Экземпляры EntityManagerFactory.

  • Разрешено создавать только один EntityManagerFactory для каждой развернутой конфигурации модуля персистентности.Любое количество экземпляров EntityManager может быть создано из данной фабрики.

  • В JVM одновременно может быть доступно более одного экземпляра фабрики диспетчера сущностей.Методы интерфейса EntityManagerFactory являются потокобезопасными.
...