JPA 2 - 在 JavaSE 中使用 EntityManager - 几个问题

发布于 2024-09-30 05:03:21 字数 1048 浏览 5 评论 0原文

我有几个关于在 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 的任何好的资源,我将不胜感激。

谢谢!

I have a couple questions regarding using the entity manager in a JavaSE environment.

I'm using the repository pattern to perform my CRUD operations on the database. There will be a base repository class like so:

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;
    }
    ...
    ...
}

I will then have classes like EmployeeRepository that will inherit Repository. These repository classes will be created in my service layer.

Is this a good way of initializing the entity manager? I'm starting to think that it's not - it seems like you should only have one entity manager per persistence unit? Where as in this case you would have an entity manager for every repository you create... How would you go about ensuring you only have one entity manager per persistence unit? Also, I noticed that the entity manager and entity manager factory methods have a close method - when should these be called? On a server terminate event?

If you know of any good sources about using JPA in JavaSE I would appreciate the info.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明月夜 2024-10-07 05:03:21

几乎。每个持久性单元只需要一个 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很明确

表示静态初始值设定项中发生意外异常的信号

...

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

那么,服务层用于划定事务边界。因此,对于每个用例,您可以创建 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 来帮助您摆脱这个样板代码。

Almost. You need just one EntityManagerFactory per persistence unit.

How would you go about ensuring you only have one EntityManagerFactory per persistence unit ?

Usually developers create an helper class with a singleton EntityManagerFactory such as

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, in other hand, is used to interact with a set of managed entity instances called persistence context.

If you want to know why i use ErrorInInitializerError, its API is clear

Signals that an unexpected exception has occurred in a static initializer

...

Is this a good way of initializing the entity manager ?

Well, the service layer is used to delimit Transaction boundary. So for each use case, you can create your EntityManager and pass by reference for each colaborator needed to help you to execute your use case.

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();
    }

}

Now imagine you need the boilerplate code shown above for each use case.

    public void forEachUseCase() {
        // Create an EntityManager
        // Begin a Transaction

        EmployeeRepository repository = new EmployeeRepository(eManager);

        // And finally, commit
    }

You can rely on Spring to help you to get rid of this boilerplate code.

粉红×色少女 2024-10-07 05:03:21

Brian,

共享 EntityManagerFactory 可以,但共享 EntityManager 不行。请参阅 Java 持久性 wiki 手册

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

所以理想情况...

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

使用单例机制的枚举可以提供... (有效Java 第二版

  1. 简洁
  2. 免费提供序列化机制
  3. 防止 EntityManagerFactory 的多个实例化,而不会出现同步问题。发生这种情况是因为枚举构造函数是在类加载时调用的,并且不能由您的代码调用。
  4. 确保 EntityManager 不被共享,除非程序员做出了错误的选择。
公共枚举 PersistenceUnitFactory
{
    PERSISTENCE_UNIT_1("persistenceUnit1"),
    PERSISTENCE_UNIT_2("persistenceUnit2");

    私有最终EntityManagerFactory emf;
    /**
     * 将持久性单元名称映射到该枚举实例。
     *
     * @param persistenceUnitName 持久化单元的名称
     * 持久化.xml
     *
     * @see #getPersistenceUnitName()
     */
    PersistenceUnitFactory(最终字符串 persistenceUnitName)
    {
        emf = Persistence.createEntityManagerFactory(persistenceUnitName);
    }

    /**
     * 创建一个新的{@link EntityManager}。切勿跨线程共享此内容。
     * 
     * @return 一个新的{@link EntityManager}
     */
    EntityManager 创建EntityManager()
    {
        返回 emf.createEntityManager();
    }
}

然后就像请求 EntityManager 一样简单...

PersistenceUnitFactory.PERSISTENCE_UNIT_1.createEntityManager();

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

Brian,

It is okay to share EntityManagerFactory, but it is not okay to share EntityManager. See the Java Persistence wikibook.

A more modern approach would be to do singletons with enums. So, assuming you don't expect to go around changing your persistence unit names (I would expect that not to occur anyhow)...

So ideally...

  1. Use a singleton for the EntityManagerFactory instance, per persistence unit.
  2. Create a new entity manager on every call to retrieve one, and don't share them.

Using an enum for the singleton mechanism provides for... (Effective Java Second edition)

  1. Being concise
  2. Provides serialization machinery for free
  3. Prevents multiple instantiation of EntityManagerFactory with no synchronization problems. This happens because enum constructors are called at class load time, and cannot be called by your code.
  4. Ensures EntityManager is not shared unless a programmer makes the incorrect choice to do so.
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();
    }
}

Then it's as simple as asking for an EntityManager...

PersistenceUnitFactory.PERSISTENCE_UNIT_1.createEntityManager();

You can add more persistence units as you need them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文