关于java:Hibernate SessionFactory与EntityManagerFactory

Hibernate SessionFactory vs. EntityManagerFactory

我是Hibernate的新手,也不清楚是否使用SessionFactoryEntityManagerFactory来获取休眠会话。 两者有什么区别? 优点缺点?


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

SessionFactorySession是休眠专用的。 EntityManager在后台调用休眠会话。并且,如果需要EntityManager中不可用的某些特定功能,则可以通过调用以下内容来获取会话:

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


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

例如:

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


使用EntityManagerFactory方法可以使我们无需额外配置即可使用@ PrePersist,@ PostPersist,@ PreUpdate等回调方法注释。

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

相关的Hibernate文档可在此处和此处找到。

相关的SOF问题和Spring论坛讨论


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

JPA:

1
2
3
4
5
6
7
8
@PersistenceContext
EntityManager entityManager;

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

SessionFactory:

1
2
3
4
5
6
7
8
9
10
11
@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可以轻松模拟。


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

1
javax.persistence.EntityManager

代替

1
org.hibernate.ejb.HibernateEntityManager

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


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


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

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