Hibernate SessionFactory与JPA EntityManagerFactory


Answers:


365

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

SessionFactory并且Session是休眠专用的。该EntityManager调用引擎盖下Hibernate的Session。并且,如果您需要某些某些特定功能,这些功能在中不可用,则EntityManager可以通过调用以下内容来获取会话:

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

2
@elpisu-实际上我不推荐。我一直只使用官方文档作为学习资源(至少在过去两年中),因此我不知道其他任何可靠的信息。但是文档足够好。
2011年

7
@Bozho我知道已经很晚了,但是使用SessionFactory和Session有什么弊端?为什么首选使用JPA?谢谢
Mickael Marrache 2011年

12
@MickaelMarrache与Hibernate API相比,首选使用JPA,因为它是Java Enterprise标准。使用JPA(并限制使用它,而不使用Hibernate特有的功能)可以提高应用程序的可移植性,即,您可以选择以最小的应用程序切换到其他持久性框架,只要该框架也符合JPA标准即可。 。
拉斯洛·范登霍克

2
仅仅是因为它是企业标准,这更好吗?我不信。标准通常发展缓慢且复杂。那么一些现实生活中的好处呢?JPA更好,因为它具有TypedQuery,可以阻止您在各地进行类型转换。
巴斯蒂安·福伊特

1
这是方法来获得SessionEntityManager,一样SessionFactory.getCurrentSession()?我的意思是,Session如果尚未创建,它将打开新的吗?它在多线程环境中如何工作?
Sarvesh

32

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

例如:

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

28
注意,unwrap()被优选的getDelegate():根据Java文档的JavaEE 6,和JavaEE的7
ryenus 2014年

22

与相比,我更喜欢JPA2 EntityManagerAPI 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可以轻松模拟。


30
您可以根据需要使任何代码复杂。return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
2015年

你怎么直接拿到的EntityManager和你呈现你必须使用的SessionFactory来获取会话..:d
JavaLearner


21

SessionFactoryEntityManagerFactory

正如我在《Hibernate用户指南》中所解释的那样,Hibernate SessionFactory扩展了JPA EntityManagerFactory,如下图所示:

JPA和Hibernate关系

因此,SessionFactory也是JPA EntityManagerFactory

无论是SessionFactoryEntityManagerFactory包含实体映射元数据,并允许您创建一个Hibernate SessionEntityManager

SessionEntityManager

就像SessionFactoryand一样EntityManagerFactory,Hibernate Session扩展了JPA EntityManager。因此,EntityManagerHibernate中提供了由定义的所有方法Session

Session和`EntityManager的翻译实体状态转换成SQL语句,如SELECT,INSERT,UPDATE和DELETE。

Hibernate与JPA引导程序

自举JPA或Hibernate应用程序时,有两种选择:

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

首选通过JPA引导。这是因为JPA FlushModeType.AUTO比旧版更好FlushMode.AUTO,因为它破坏了本机SQL查询的读写一致性

将JPA展开为休眠状态

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

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

您可以Sessionfactory使用以下unwrap方法轻松访问基础:

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

JPA可以完成相同的操作EntityManager。如果您EntityManager通过@PersistenceContext注释注入:

@PersistenceContext
private EntityManager entityManager;

您可以Session使用以下unwrap方法轻松访问基础:

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

结论

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


2

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

javax.persistence.EntityManager

代替

org.hibernate.ejb.HibernateEntityManager

同样,对于EntityManagerFactory,请使用javax接口。这样,代码就可以松散耦合。如果有一个比休眠更好的JPA 2实现,则切换将很容易。在极端情况下,我们可以将强制类型转换为HibernateEntityManager。


2

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


1

EntityManager接口类似于休眠状态下的sessionFactory。EntityManager在javax.persistance包下,而session和sessionFactory在org.hibernate.Session / sessionFactory包下。

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


您的答案是正确的,但与李三蕴在其评论中提及的答案基本相同...重复。
RWC '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.