【问题标题】:JPA 2 - Using the EntityManager in JavaSE - a couple of questionsJPA 2 - 在 JavaSE 中使用 EntityManager - 几个问题
【发布时间】:2011-05-03 05:40:53
【问题描述】:

我有几个关于在 JavaSE 环境中使用实体管理器的问题。

我正在使用存储库模式对数据库执行我的 CRUD 操作。会有一个像这样的基础存储库类:

public class Repository<T> implements IRepository<T> {

    private EntityManager em;
    private String persistenceUnitName;

    public Repository(String persistenceUnitName) {
        this.persistenceUnitName = persistenceUnitName;
    }

    @Override
    public T find(Class<T> type, Object id) {
        return em.find(type, id);
    }

    private EntityManager getEntityManager() {
        if (this.em == null) {
            EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);

            em = emf.createEntityManager();
        }

        return em;
    }
    ...
    ...
}

然后,我将拥有像 EmployeeRepository 这样的类来继承 Repository。这些存储库类将在我的服务层中创建。

这是初始化实体管理器的好方法吗?我开始认为它不是 - 似乎每个持久性单元应该只有一个实体管理器?在这种情况下,您将为您创建的每个存储库都有一个实体管理器......您将如何确保每个持久性单元只有一个实体管理器?另外,我注意到实体管理器和实体管理器工厂方法有一个 close 方法 - 什么时候应该调用它们?在服务器终止事件上?

如果您知道任何关于在 JavaSE 中使用 JPA 的好资料,我将不胜感激。

谢谢!

【问题讨论】:

    标签: java hibernate jpa jpa-2.0 entitymanager


    【解决方案1】:

    几乎。每个持久性单元只需要一个 EntityManagerFactory。

    您将如何确保每个持久性单元只有一个 EntityManagerFactory ?

    通常开发人员使用单例 EntityManagerFactory 创建一个帮助类,例如

    public class EntityManagerFactoryHelper {
    
        private static EntityManagerFactory factory;
    
        static {
            try {
               // Set up factory right here
            } catch(ExceptionInInitializerError e) {
                throw e;
            }
        }
    
        public static EntityManagerFactory getFactory() {
            return this.factory;
        }
    
    }
    

    另一方面,EntityManager 用于与一组称为持久性上下文的托管实体实例进行交互。

    如果你想知道我为什么使用ErrorInInitializerError,它的API很清楚

    表示在静态初始化程序

    中发生了意外异常

    ...

    这是初始化实体管理器的好方法吗?

    嗯,服务层是用来划定Transaction边界的。所以对于每个用例,您可以创建您的 EntityManager 并为每个合作者传递参考,以帮助您执行您的用例。

    public static br.com.helper.EntityManagerFactoryHelper.getFactory;
    
    public EmployeeService {
    
        public void doSomething() {
            EntityManager eManager = getFactory().createEntityManager();
            eManager.getTransaction().begin();
    
            EmployeeRepository repository = new EmployeeRepository(eManager);
    
            eManager.getTransaction().commit();
        }
    
    }
    

    现在假设您需要上面显示的每个用例的样板代码。

        public void forEachUseCase() {
            // Create an EntityManager
            // Begin a Transaction
    
            EmployeeRepository repository = new EmployeeRepository(eManager);
    
            // And finally, commit
        }
    

    您可以依靠Spring 来帮助您摆脱这种样板代码。

    【讨论】:

    • 我有点晚了,但是你知道吗,如果你使用的是容器管理的持久性,你可以通过 : (ie EntityManager manager = (EntityManager) context.lookup(jndiName); ),是不是每次 EM 都返回一个新的 EM?它是在幕后抽出 EM 的 EMF,还是只是链接到单个线程的全局 EM?
    【解决方案2】:

    布赖恩,

    EntityManagerFactory 可以共享,EntityManager 不能共享。请参阅Java Persistence wikibook

    更现代的方法是使用枚举进行单例。因此,假设您不希望更改持久性单元名称(我希望无论如何都不会发生)...

    所以理想...

    1. 为每个持久性单元的 EntityManagerFactory 实例使用单例。
    2. 在每次调用时创建一个新的实体管理器以检索一个,并且不要共享它们。

    为单例机制使用枚举提供... (Effective Java Second edition)

    1. 简洁
    2. 免费提供序列化机制
    3. 防止 EntityManagerFactory 的多次实例化而没有同步问题。发生这种情况是因为枚举构造函数在类加​​载时被调用,并且不能被您的代码调用。
    4. 确保 EntityManager 不被共享,除非程序员做出了错误的选择。
    public enum PersistenceUnitFactory
    {
        PERSISTENCE_UNIT_1("persistenceUnit1"),
        PERSISTENCE_UNIT_2("persistenceUnit2");
    
        private final EntityManagerFactory emf;
        /**
         * Maps the persistence unit name to this instance of the enum.
         *
         * @param persistenceUnitName the name of the peristence unit in
         *                            persistence.xml
         *
         * @see #getPersistenceUnitName()
         */
        PersistenceUnitFactory(final String persistenceUnitName)
        {
            emf = Persistence.createEntityManagerFactory(persistenceUnitName);
        }
    
        /**
         * Creates a new {@link EntityManager}.  NEVER share this across threads.
         * 
         * @return a new {@link EntityManager}
         */
        EntityManager createEntityManager()
        {
            return emf.createEntityManager();
        }
    }
    

    那么它就像请求一个EntityManager一样简单......

    PersistenceUnitFactory.PERSISTENCE_UNIT_1.createEntityManager();
    

    您可以根据需要添加更多持久性单元。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-09
      • 2012-04-18
      • 2013-07-25
      • 2011-01-22
      • 1970-01-01
      • 2016-01-03
      • 2012-08-24
      • 1970-01-01
      相关资源
      最近更新 更多