【问题标题】:EntityManager in multithread app? [duplicate]多线程应用程序中的EntityManager? [复制]
【发布时间】:2014-01-26 15:46:39
【问题描述】:

如何在多线程应用程序中使用 Hibernate EntityManager(例如,每个客户端连接在服务器上启动它自己的线程)。

EntityManager 是否应该只由 EntityManagerFactory 创建一次,例如:

private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit");
private static EntityManager em = emf.createEntityManager();
    public static EntityManager get() {
        return em;
    }

或者我是否必须为每个线程以及每个关闭 EM 的事务重新创建实体管理器?

我的 CRUD 方法如下所示:

public void save(T entity) {
    em.getTransaction().begin();
    em.persist(entity);
    em.getTransaction().commit();
    em.close();
}

public void delete(T entity) {
    em.getTransaction().begin();
    em.remove(entity);
    em.getTransaction().commit();
    em.close();
}

我必须在每个.begin() 之前运行emf.createEntityManager() 吗?还是因为每个人都在使用自己的缓存创建自己的 EntityManager 实例而遇到麻烦?

【问题讨论】:

  • 因此,显然我将拥有一个 EMF,并为每个线程创建一个新的 EM。但仍然:如果我在每次交易后关闭 EM,我是否需要每次(在一个线程中多次)重新创建 EM?
  • 关闭 EM 后就不能再使用了。但是您当然可以使用一个 EM 进行多笔交易。请记住,EM 是一种轻量级对象,专为廉价创建而设计。确定您的工作单元并为它们使用一个 EM。您可能会觉得 reference documentation 很有趣。

标签: java database hibernate entitymanager


【解决方案1】:

5.1. Entity manager and transaction scopes:

EntityManager 是一个廉价的、非线程安全的对象,应该使用一次,用于 单个业务流程,单个工作单元,然后丢弃。

这完美地回答了您的问题。不要通过线程共享 EM。只要这些交易是工作单元的一部分,就可以将一个 EM 用于多个交易。

此外,在 closed 之后,您将无法使用 EntityManger:

调用 close 方法后,EntityManager 实例上的所有方法以及从中获取的任何 Query、TypedQuery 和 StoredProcedureQuery 对象都将抛出 IllegalStateException。

考虑这样的事情:

public class Controller {

    private EntityManagerFactory emf;

    public void doSomeUnitOfWork(int id) {
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        CrudDao dao = new CrudDao(em);

        Entity entity = dao.get(id);
        entity.setName("James");
        dao.save(entity);

        em.getTransaction.commit();
        em.close();
    }

}

【讨论】:

  • 是的,因为 EM 不是线程安全的,如果我围绕它创建一个包装器并在内部调用 EM 的保存/更新的包装器中包含“同步”保存/更新方法,它是否可以跨多个线程使用.我也从不清除/关闭 EM 吗?我认为同时读写仍然存在问题。你能告诉我你的cmets吗?
  • 为什么要在创建 EM 成本低廉的情况下增加如此复杂性?如果您的线程共享工作单元所在的相同上下文,我只能想象这是有道理的。
  • 是的,为每个线程创建一个单独的 EM 绝对是最好的选择。我只是好奇我上面说的是否足够安全。您能否对“相同的上下文”部分有所了解。很抱歉我没听懂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多