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

Bri*_*asa 5 java hibernate jpa entitymanager jpa-2.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;
    }
    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

谢谢!

Art*_*ald 4

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

}
Run Code Online (Sandbox Code Playgroud)

另一方面,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();
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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

        EmployeeRepository repository = new EmployeeRepository(eManager);

        // And finally, commit
    }
Run Code Online (Sandbox Code Playgroud)

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