284

我是 Hibernate 的新手,我不确定是使用 HibernateSessionFactory还是 JPAEntityManagerFactory来创建 Hibernate Session

这两者有什么区别?使用它们各自的优点和缺点是什么?

4

8 回答 8

392

更喜欢EntityManagerFactoryEntityManager。它们由 JPA 标准定义。

SessionFactory并且Session是特定于休眠的。EntityManager调用引擎盖下的休眠会话。并且如果您需要一些在 中没有的特定功能EntityManager,您可以通过调用获取会话:

Session session = entityManager.unwrap(Session.class);
于 2011-04-12T19:52:32.360 回答
52

SessionFactory对比EntityManagerFactory

正如我在Hibernate User Guide中解释的那样,HibernateSessionFactory扩展了 JPA EntityManagerFactory,如下图所示:

JPA 和 Hibernate 的关系

所以,这SessionFactory也是一个 JPA EntityManagerFactory

SessionFactory和都EntityManagerFactory包含实体映射元数据,并允许您创建 HibernateSessionEntityManager.

Session对比EntityManager

就像SessionFactoryand一样EntityManagerFactory,HibernateSession扩展了 JPA EntityManager。因此,由 定义的所有方法EntityManager都可以在 Hibernate 中使用Session

Session`EntityManager 将实体状态转换转换为 SQL 语句,如 SELECT、INSERT、UPDATE 和 DELETE。

Hibernate 与 JPA 引导程序

在引导 JPA 或 Hibernate 应用程序时,您有两种选择:

  1. 您可以通过 Hibernate 本机机制进行引导,并SessionFactory通过BootstrapServiceRegistryBuilder. 如果您使用 Spring,Hibernate 引导是通过 完成的LocalSessionFactoryBean如此 GitHub 示例所示
  2. 或者,您可以EntityManagerFactory通过Persistence类或EntityManagerFactoryBuilder. 如果您使用 Spring,则 JPA 引导程序是通过 完成的LocalContainerEntityManagerFactoryBean如此 GitHub 示例所示

通过 JPA 引导是首选。这是因为 JPAFlushModeType.AUTO是比传统更好的选择FlushMode.AUTO,它破坏了原生 SQL 查询的 read-your-writes 一致性

将 JPA 解包到 Hibernate

EntityManagerFactory此外,如果您通过 JPA 引导,并且您已通过@PersistenceUnit注释注入:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

Sessionfactory您可以使用以下方法轻松访问底层unwrap

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);

JPA 也可以这样做EntityManagerEntityManager如果你通过@PersistenceContext注解注入:

@PersistenceContext
private EntityManager entityManager;

Session您可以使用以下方法轻松访问底层unwrap

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

结论

因此,您应该通过 JPA 引导,使用EntityManagerFactoryand EntityManager,并且仅当您想要访问 JPA 中不可用的某些特定于 Hibernate 的方法(例如通过其自然标识符获取实体)时,才将它们解包到其关联的 Hibernate 接口。

于 2020-02-22T17:14:51.787 回答
32

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

前任:

Session session = (Session) entityManager.getDelegate();
于 2013-01-19T06:51:10.220 回答
24

我更喜欢 JPA2 EntityManagerAPI SessionFactory,因为它感觉更现代。一个简单的例子:

JPA:

@PersistenceContext
EntityManager entityManager;

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

会话工厂:

@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 可以很容易地模拟。

于 2015-03-04T08:46:48.110 回答
23

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

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

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

相关 SOF 问题Spring 论坛讨论

于 2013-09-09T10:29:29.670 回答
2

By using EntityManager, code is no longer tightly coupled with hibernate. But for this, in usage we should use :

javax.persistence.EntityManager

instead of

org.hibernate.ejb.HibernateEntityManager

Similarly, for EntityManagerFactory, use javax interface. That way, the code is loosely coupled. If there is a better JPA 2 implementation than hibernate, switching would be easy. In extreme case, we could type cast to HibernateEntityManager.

于 2014-09-26T11:56:02.397 回答
2

EntityManagerFactory 是标准实现,在所有实现中都是相同的。如果您为任何其他提供商(如 EclipseLink)迁移 ORM,则处理事务的方法不会发生任何变化。相反,如果您使用 hibernate 的会话工厂,它与 hibernate API 绑定,无法迁移到新的供应商。

于 2019-07-07T16:16:55.177 回答
1

EntityManager 接口类似于 hibernate 中的 sessionFactory。EntityManager 在 javax.persistance 包下,但 session 和 sessionFactory 在 org.hibernate.Session/sessionFactory 包下。

实体管理器是特定于 JPA 的,而 session/sessionFactory 是特定于休眠的。

于 2018-07-24T10:16:42.687 回答