Hibernate SessionFactory与EntityManagerFactory

elp*_*isu 234 java hibernate jpa sessionfactory hibernate-entitymanager

我是Hibernate的新手,不知道是否要使用SessionFactoryEntityManagerFactory获取hibernate会话.两者有什么区别?优点缺点?

Boz*_*zho 351

喜欢EntityManagerFactoryEntityManager.它们由JPA标准定义.

SessionFactory并且Session是特定于休眠的.该EntityManager调用引擎盖下Hibernate的Session.如果您需要一些不可用的特定功能EntityManager,您可以通过调用以下方式获取会话:

Session session = entityManager.unwrap(Session.class);
Run Code Online (Sandbox Code Playgroud)

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

Vla*_*cea 45

SessionFactory 对比 EntityManagerFactory

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

JPA 和 Hibernate 的关系

所以,这SessionFactory也是一个 JPA EntityManagerFactory

theSessionFactory和 theEntityManagerFactory都包含实体映射元数据,并允许您创建 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是比 legacy 更好的选择FlushMode.AUTO,它破坏了本机 SQL 查询的 read-your-writes 一致性

将 JPA 解包到 Hibernate

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

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
Run Code Online (Sandbox Code Playgroud)

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

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
Run Code Online (Sandbox Code Playgroud)

对 JPA 也可以这样做EntityManager。如果您EntityManager通过@PersistenceContext注释注入:

@PersistenceContext
private EntityManager entityManager;
Run Code Online (Sandbox Code Playgroud)

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

Session session = entityManager.unwrap(Session.class);
Run Code Online (Sandbox Code Playgroud)

结论

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


toy*_*toy 30

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

例如:

Session session = (Session) entityManager.getDelegate();
Run Code Online (Sandbox Code Playgroud)

  • 请注意,根据java文档,`unwrap()`是首选的**而不是`getDelegate()`:[javaee 6](http://docs.oracle.com/javaee/6/api/javax/ persistence/EntityManager.html#getDelegate())和[javaee 7](http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#getDelegate()). (27认同)

Kum*_*hav 21

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

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

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

相关SOF问题春季论坛讨论


Bas*_*igt 19

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

JPA:

@PersistenceContext
EntityManager entityManager;

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

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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果需要,您可以使任何代码变得复杂.`return sessionFactory.getCurrentSession().createQuery("from user where id = 1").list()` (28认同)