何时应创建/打开 EntityManagerFactory 实例?

2022-09-01 15:13:42

好的,我阅读了一堆关于如何在单例中编写实体管理器工厂的文章/示例。

其中一个对我来说最容易理解:

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

我了解到EntityManagerFactory(EMF)应该只在应用程序范围内创建一次。

还要确保在使用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
  • EntityManagerFactory 实例是重量级对象。每个工厂都可能维护元数据缓存、对象状态缓存、EntityManager 池、连接池等。如果您的应用程序不再需要 EntityManagerFactory,则应将其关闭以释放这些资源。

  • 当 EntityManagerFactory 关闭时,该工厂中的所有 EntityManager 以及由这些 EntityManager 管理的所有实体都将变为无效。

  • 让工厂长期开放比反复创建和关闭新工厂要好得多。因此,大多数应用程序永远不会关闭工厂,或者仅在应用程序退出时关闭工厂。

  • 只有需要具有不同配置的多个工厂的应用程序才有明显的理由创建和关闭多个 EntityManagerFactory 实例。

  • 只允许为每个部署的持久性单元配置创建一个 EntityManagerFactory。可以从给定的工厂创建任意数量的 EntityManager 实例。

  • 多个实体管理器工厂实例可能同时在 JVM 中可用。EntityManagerFactory 接口的方法是线程安全的。

答案 2

推荐