ChatGPT解决这个技术问题 Extra ChatGPT

Hibernate SessionFactory 与 JPA EntityManagerFactory

我是 Hibernate 的新手,我不确定是使用 Hibernate SessionFactory 还是 JPA EntityManagerFactory 来创建 Hibernate Session

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

这个重复问题的答案非常好。 stackoverflow.com/questions/23445830/…

B
Bozho

首选 EntityManagerFactoryEntityManager。它们由 JPA 标准定义。

SessionFactorySession 是特定于休眠的。 EntityManager 在后台调用休眠会话。如果您需要EntityManager中没有的一些特定功能,您可以通过调用获取会话:

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

@elpisu - 实际上我不能推荐。我一直只使用官方文档作为学习资源(至少在过去 2 年中),所以我不知道其他可靠的东西。但是文档已经足够好了。
@Bozho我知道已经很晚了,但是使用SessionFactory和Session有什么缺点?为什么首选使用 JPA?谢谢
@MickaelMarrache 使用 JPA 优于 Hibernate API,因为它是 Java 企业标准。使用 JPA(并限制自己使用它,而不使用 Hibernate 特定的功能)提高了应用程序的可移植性,即您可以选择切换到不同的持久性框架,而对应用程序的更改最少,只要该框架也符合 JPA 标准.
仅仅因为它是企业标准就更好吗?我不信。标准通常发展缓慢且复杂。一些现实生活中的好处呢? JPA 更好,因为它有 TypedQuery,可以阻止你到处进行类型转换。
这种从 EntityManager 获取 Session 的方法是否与 SessionFactory.getCurrentSession() 相同?我的意思是,如果它尚未创建,它会打开新的 Session 吗?它在多线程环境中如何工作?
V
Vlad Mihalcea

SessionFactory 与 EntityManagerFactory

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

https://i.stack.imgur.com/5aTCH.png

因此,SessionFactory 也是 JPA EntityManagerFactory

SessionFactoryEntityManagerFactory 都包含实体映射元数据,并允许您创建 Hibernate SessionEntityManager

Session 与 EntityManager

SessionFactoryEntityManagerFactory 一样,Hibernate Session 扩展了 JPA EntityManager。因此,由 EntityManager 定义的所有方法都在 Hibernate Session 中可用。

Session 和 `EntityManager 将 entity state transitions 转换为 SQL 语句,如 SELECT、INSERT、UPDATE 和 DELETE。

Hibernate 与 JPA 引导程序

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

您可以通过 Hibernate 原生机制进行引导,并通过 BootstrapServiceRegistryBuilder 创建一个 SessionFactory。如果您使用的是 Spring,Hibernate 引导是通过 LocalSessionFactoryBean 完成的,如此 GitHub 示例所示。或者,您可以通过 Persistence 类或 EntityManagerFactoryBuilder 创建 JPA EntityManagerFactory。如果您使用的是 Spring,则 JPA 引导是通过 LocalContainerEntityManagerFactoryBean 完成的,如此 GitHub 示例所示。

通过 JPA 引导是首选。这是因为 JPA FlushModeType.AUTO 是比旧版 FlushMode.AUTO 更好的选择,旧版 breaks read-your-writes consistency for native SQL queries

将 JPA 解包到 Hibernate

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

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

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

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

JPA EntityManager 也可以做到这一点。如果您通过 @PersistenceContext 注释注入 EntityManager

@PersistenceContext
private EntityManager entityManager;

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

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

结论

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


P
Peter Butkovic

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

前任:

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

请注意,根据 java 文档:javaee 6javaee 7unwrap() 优于 getDelegate()
v
vphilipnyc

我更喜欢 JPA2 EntityManager API 而不是 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 可以很容易地模拟。


如果你愿意,你可以让任何代码变得复杂。 return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
您是如何直接获得 entityManager 的,并且表明您必须使用 sessionfactory 来获取会话..:D
C
Community

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

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

可以在 herehere 中找到相关的 Hibernate 文档。

Related SOF QuestionSpring Forum discussion


S
Sairam Krish

通过使用 EntityManager,代码不再与休眠紧密耦合。但是为此,在使用中我们应该使用:

javax.persistence.EntityManager

代替

org.hibernate.ejb.HibernateEntityManager

同样,对于 EntityManagerFactory,使用 javax 接口。这样,代码是松耦合的。如果有比 hibernate 更好的 JPA 2 实现,切换会很容易。在极端情况下,我们可以将类型转换为 HibernateEntityManager。


A
ABODE

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


A
Avvappa Hegadyal

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

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


您的答案是正确的,但与 Sangyun Lee 在他的评论中提到的答案基本相同……所以重复。
SessionFactory ~= EntityManagerFactory,而不是 EntityManager。错误的答案。