我是Hibernate的新手,我不确定是否使用Hibernate SessionFactory或JPA EntityManagerFactory来创建Hibernate会话。

这两者有什么不同?使用这些工具的优缺点是什么?


当前回答

我更喜欢JPA2 EntityManager API而不是SessionFactory,因为它感觉更现代。举个简单的例子:

JPA:

@PersistenceContext
EntityManager entityManager;

public List<MyEntity> findSomeApples() {
  return entityManager
     .createQuery("from MyEntity where apples=7", MyEntity.class)
     .getResultList();
}

SessionFactory:

@Autowired
SessionFactory sessionFactory;

public List<MyEntity> findSomeApples() {
  Session session = sessionFactory.getCurrentSession();
  List<?> result = session.createQuery("from MyEntity where apples=7")
      .list();
  @SuppressWarnings("unchecked")
  List<MyEntity> resultCasted = (List<MyEntity>) result;
  return resultCasted;
}

我认为很明显,第一个看起来更干净,也更容易测试,因为EntityManager很容易被模仿。

其他回答

使用EntityManagerFactory方法允许我们使用回调方法注释,如@PrePersist, @PostPersist,@PreUpdate,而不需要额外的配置。

在使用SessionFactory时使用类似的回调将需要额外的努力。

相关Hibernate文档可以在这里和这里找到。

有关SOF问题和春季论坛讨论

我想补充一点,你也可以通过从EntityManager调用getDelegate()方法来获取Hibernate的会话。

ex:

Session session = (Session) entityManager.getDelegate();

优先选择EntityManagerFactory和EntityManager。它们是由JPA标准定义的。

SessionFactory和Session是特定于休眠的。EntityManager调用底层的hibernate会话。如果你需要一些EntityManager中没有的特性,你可以通过调用:

Session session = entityManager.unwrap(Session.class);

我更喜欢JPA2 EntityManager API而不是SessionFactory,因为它感觉更现代。举个简单的例子:

JPA:

@PersistenceContext
EntityManager entityManager;

public List<MyEntity> findSomeApples() {
  return entityManager
     .createQuery("from MyEntity where apples=7", MyEntity.class)
     .getResultList();
}

SessionFactory:

@Autowired
SessionFactory sessionFactory;

public List<MyEntity> findSomeApples() {
  Session session = sessionFactory.getCurrentSession();
  List<?> result = session.createQuery("from MyEntity where apples=7")
      .list();
  @SuppressWarnings("unchecked")
  List<MyEntity> resultCasted = (List<MyEntity>) result;
  return resultCasted;
}

我认为很明显,第一个看起来更干净,也更容易测试,因为EntityManager很容易被模仿。

EntityManagerFactory是标准实现,它在所有实现中都是一样的。如果您将ORM迁移到任何其他提供者(如EclipseLink),则处理事务的方法不会有任何变化。相反,如果使用hibernate的会话工厂,它就绑定到hibernate api,不能迁移到新的供应商。