【问题标题】:When should EntityManagerFactory instance be created/opened?什么时候应该创建/打开 EntityManagerFactory 实例?
【发布时间】:2011-05-31 10:42:18
【问题描述】:

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

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

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 必须是单例的?我阅读了有关并发问题的文章,但由于我没有多线程语法经验,所以我并不清楚这个想法。

【问题讨论】:

  • "为什么 EMF 必须是单例如此糟糕???"这句话我可能应该打开另一个问题....

标签: java jpa singleton entitymanager


【解决方案1】:
  • EntityManagerFactory 实例是 重量级的物体。每个工厂 可能会维护元数据缓存, 对象状态缓存,EntityManager 池、连接池等。如果 您的应用程序不再需要 EntityManagerFactory,你应该 关闭它以释放这些资源。

  • 当 EntityManagerFactory 关闭时, 该工厂的所有 EntityManagers, 并通过扩展管理所有实体 通过那些 EntityManagers,成为 无效。

  • 最好还是建个工厂 开放时间比 反复创建和关闭新的 工厂。因此,大多数应用 永远不会关闭工厂,或者只是 当应用程序运行时关闭它 退出。

  • 仅适用于需要 多家工厂不同 配置有一个明显的原因 创建和关闭多个 EntityManagerFactory 实例。

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

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

【讨论】:

  • 我认为'EntityManagerFactory'不应该为在线网络应用程序关闭。
  • 它应该被关闭,但只有在 Web 应用程序停止时(用户停止它或取消部署它)。示例:使用 JSF 时从 ServletContextListener 接口实现 contextDestroyed 方法
  • @pvm14 是的,当然。如果必须按照您的方式进行并且如果文档中的所有内容都在并且每个人都理解,那么stackoverlow就不会出现。人们没有不必要地投票。如果您不喜欢,请留下它,不要发布无关的 cmets,而是尝试添加更多信息、细节、错误等,如果可以的话,这将对每个人都有帮助。
  • 我对答案的唯一问题是,在我公认的有限经验中,实际上需要打开/关闭 EMF - 至少来自客户端,否则客户端甚至会挂起而不记录一个错误。当 JPA 从服务器运行时,性能可能会有所不同。
  • @Thufir 已经提到 EntityManagerFactory 实例是一个重量级对象,应该只在应用程序初始化时创建一次,并在取消/终止时关闭。如果有很多客户端,最好不要打开/关闭工厂实例。
猜你喜欢
  • 2019-06-13
  • 2011-03-21
  • 2011-09-11
  • 1970-01-01
  • 2013-01-16
  • 2018-03-02
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
相关资源
最近更新 更多