这两者之间有什么区别?使用它们各自的优缺点是什么?
推荐使用JPA标准定义的EntityManagerFactory
和EntityManager
。
SessionFactory
和Session
是特定于Hibernate的。 EntityManager
在幕后调用了Hibernate会话。如果您需要一些在EntityManager
中不可用的特定功能,可以通过调用以下代码获取会话:
Session session = entityManager.unwrap(Session.class);
EntityManager
获取Session
的方法,和SessionFactory.getCurrentSession()
一样吗?我的意思是,如果还没有创建Session
,它会打开新的Session
吗?在多线程环境下它是如何工作的? - SarveshSessionFactory
vs. EntityManagerFactory
如我在Hibernate用户指南中解释的那样,Hibernate的SessionFactory
扩展了JPA的EntityManagerFactory
,如下图所示:
因此,SessionFactory
也是一个JPA EntityManagerFactory
。
无论是SessionFactory
还是EntityManagerFactory
都包含实体映射元数据,并允许您创建一个Hibernate的Session
或一个EntityManager
。
Session
vs. EntityManager
和SessionFactory
、EntityManagerFactory
一样,Hibernate的Session
也扩展了JPA的EntityManager
。因此,Session
中定义的所有方法都可在Hibernate中使用。
Session
和`EntityManager
将实体状态转换成SQL语句,如SELECT、INSERT、UPDATE和DELETE。
在启动JPA或Hibernate应用程序时,您有两个选择:
BootstrapServiceRegistryBuilder
创建一个SessionFactory
。如果您正在使用Spring,则Hibernate引导是通过LocalSessionFactoryBean
完成的,例如此GitHub示例。Persistence
类或EntityManagerFactoryBuilder
创建一个JPA EntityManagerFactory
。如果您正在使用Spring,则JPA引导是通过LocalContainerEntityManagerFactoryBean
完成的,例如此GitHub示例。通过JPA引导是更好的选择。这是因为JPA的FlushModeType.AUTO
比传统的FlushMode.AUTO
更好,后者会破坏本机SQL查询的读写一致性。
而如果您通过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引导程序,使用EntityManagerFactory
和EntityManager
,并仅在想要访问一些Hibernate特定方法(例如通过其自然标识符获取实体)时,将其解包到相关的Hibernate接口。
我更喜欢JPA2 EntityManager
API 而不是 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可以轻松模拟。
return sessionFactory.getCurrentSession().createQuery("from User where id=1").list()
。 - wstEntityManagerFactory是标准实现,不同的ORM都是相同的。如果你将ORM迁移到其他提供商(如EclipseLink),在处理事务时不会有任何变化。与之相反,如果您使用Hibernate的session工厂,则与Hibernate API绑定,无法迁移到新的供应商。
javax.persistence.EntityManager
org.hibernate.ejb.HibernateEntityManager
EntityManager接口类似于hibernate中的sessionFactory。 javax.persistence包下有EntityManager,而org.hibernate.Session/sessionFactory包下有session和sessionFactory。
Entity manager是JPA特有的,而session/sessionFactory则是hibernate特有的。