【问题标题】:Different ways of getting the EntityManager获取 EntityManager 的不同方法
【发布时间】:2012-06-25 19:14:35
【问题描述】:

我看到的用于创建 EntityManager 的惯用语是这样的:

public class BaseDao {
    private static final String PERSISTENCE_UNIT_NAME = "Employee";

    EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

    public EntityManager getEntityManager() {
      return factory.createEntityManager();
    } 
}

那么就是这样使用的:

Employee emp = new Employee();
emp.setName("Joe M");
getEntityManager().persist(emp);

问题是为什么不这样做:

public class BaseDao{
    private static final String PERSISTENCE_UNIT_NAME = "Employee";
    EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    private EntityManager entityManager = null;


public void setEntityManger() {
    EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    this.entityManager = factory.createEntityManager();

    }

    public EntityManager getEntityManager() {
        return this.entityManager;
    }
}

换句话说,是否需要始终通过factory.createEntityManager() 获取实体管理器?还是可以将其创建为实例(甚至静态)变量并像那样检索?

为了澄清,我说的是不使用 EJB 或 Spring 容器的环境。

谢谢。

【问题讨论】:

    标签: java jpa entitymanager


    【解决方案1】:

    两种方法可以创建EntityManager 实例。

    一种方式是用于 SDK 应用程序,我在单元测试中经常使用这种方式。这就是您的示例中的内容:

    EntityManagerFactory factory = 
      Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    

    在企业应用程序中,您可以让容器为您创建它们并在需要时注入它们。

    EntityManager 只是一个 JDBC 连接的包装器。它的重量很轻,可以在没有性能损失的情况下创建和销毁。

    请记住,EntityManager 不是线程安全的,因此如果您有一个实例,您可能需要同步对它的访问。详情请见transaction basics


    我会这样做(大致):

    public class BaseDao{
      private static final String PERSISTENCE_UNIT_NAME = "Employee";
      private static EntityManagerFactory factory = 
        Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    
      public void create(MyEntiy person){
        EntityManager em = factory.createEntityManager();
        em.getTransaction().begin();
        // do what ever you need 
        em.getTransaction().commit();
        em.close();
      }
    
      // add more methods to the dao.
    }
    

    一旦你得到这个原型并准备好,你就可以使用一个通用的 DAO。

    【讨论】:

    • 谢谢 - 我在原始帖子中添加了一条注释,说明我不在企业环境中,因此容器注入不可用。不过,我确实注意到您对线程安全的评论。
    • RE 线程安全 - 我假设您参考我的示例,因为由容器注入和管理的 EntityManager 将是线程安全的。
    • 不,它不会是线程安全的,但是容器会在需要时创建一个新容器(我可能是错的),所以它看起来是线程安全的。如果您不在企业环境中,那么我认为创建工厂 EntityManagerFactory 的一个静态实例没有问题,并在需要时调用它来获取 EntityManager 的实例。并且不要忘记在每次交易后关闭它们。该线程显示了一个对您有用的代码。 stackoverflow.com/questions/7329873/…
    • Mansour,我的问题不是关于静态 EMF,然后在其上调用 createEntityManager() (这是我帖子中的第一个示例,也是您在链接中指向的示例)。我的问题是关于创建实例或静态 EM,然后使用它。
    【解决方案2】:

    今天你可能应该看看 spring-data 和 @PersistanceUnit 来管理你的 EntityManager。

    EntityManager 不仅仅是 JDBC 连接的包装器。它定义了持久性上下文的范围,它定义了提交事务时(当您将查询刷新到数据库时)应该执行的工作单元。在持久化上下文中,您还可以保证数据库中的给定实体将产生相同的 Java 对象,无论您是直接加载它,还是通过另一个实体的 OneToMany 关系访问它。

    关于在非弹簧设置中获取 EntityManagerFactory 的原始问题。你只需调用

    Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    

    此方法是一种静态工厂方法,根据您的 JPA 实现,您可以为同一个 PU 获得相同的实例,或者为包装底层持久性会话(每个 PU 有一个)的浅层包装器。

    【讨论】:

      猜你喜欢
      • 2014-11-27
      • 2011-05-16
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      相关资源
      最近更新 更多