我是 Hibernate 的新手,我不确定是使用 HibernateSessionFactory
还是 JPAEntityManagerFactory
来创建 Hibernate Session
。
这两者有什么区别?使用它们各自的优点和缺点是什么?
我是 Hibernate 的新手,我不确定是使用 HibernateSessionFactory
还是 JPAEntityManagerFactory
来创建 Hibernate Session
。
这两者有什么区别?使用它们各自的优点和缺点是什么?
更喜欢EntityManagerFactory
和EntityManager
。它们由 JPA 标准定义。
SessionFactory
并且Session
是特定于休眠的。EntityManager
调用引擎盖下的休眠会话。并且如果您需要一些在 中没有的特定功能EntityManager
,您可以通过调用获取会话:
Session session = entityManager.unwrap(Session.class);
SessionFactory
对比EntityManagerFactory
正如我在Hibernate User Guide中解释的那样,HibernateSessionFactory
扩展了 JPA EntityManagerFactory
,如下图所示:
所以,这SessionFactory
也是一个 JPA EntityManagerFactory
。
SessionFactory
和都EntityManagerFactory
包含实体映射元数据,并允许您创建 HibernateSession
或EntityManager
.
Session
对比EntityManager
就像SessionFactory
and一样EntityManagerFactory
,HibernateSession
扩展了 JPA EntityManager
。因此,由 定义的所有方法EntityManager
都可以在 Hibernate 中使用Session
。
和Session
`EntityManager 将实体状态转换转换为 SQL 语句,如 SELECT、INSERT、UPDATE 和 DELETE。
在引导 JPA 或 Hibernate 应用程序时,您有两种选择:
SessionFactory
通过BootstrapServiceRegistryBuilder
. 如果您使用 Spring,Hibernate 引导是通过 完成的LocalSessionFactoryBean
,如此 GitHub 示例所示。EntityManagerFactory
通过Persistence
类或EntityManagerFactoryBuilder
. 如果您使用 Spring,则 JPA 引导程序是通过 完成的LocalContainerEntityManagerFactoryBean
,如此 GitHub 示例所示。通过 JPA 引导是首选。这是因为 JPAFlushModeType.AUTO
是比传统更好的选择FlushMode.AUTO
,它破坏了原生 SQL 查询的 read-your-writes 一致性。
EntityManagerFactory
此外,如果您通过 JPA 引导,并且您已通过@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 引导,使用EntityManagerFactory
and EntityManager
,并且仅当您想要访问 JPA 中不可用的某些特定于 Hibernate 的方法(例如通过其自然标识符获取实体)时,才将它们解包到其关联的 Hibernate 接口。
我想补充一点,你也可以通过调用getDelegate()
from 的方法来获取 Hibernate 的会话EntityManager
。
前任:
Session session = (Session) entityManager.getDelegate();
我更喜欢 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 可以很容易地模拟。
使用 EntityManagerFactory 方法允许我们使用回调方法注释,如 @PrePersist、@PostPersist、@PreUpdate,而无需额外配置。
在使用 SessionFactory 时使用类似的回调将需要额外的努力。
By using EntityManager, code is no longer tightly coupled with hibernate. But for this, in usage we should use :
javax.persistence.EntityManager
instead of
org.hibernate.ejb.HibernateEntityManager
Similarly, for EntityManagerFactory, use javax interface. That way, the code is loosely coupled. If there is a better JPA 2 implementation than hibernate, switching would be easy. In extreme case, we could type cast to HibernateEntityManager.
EntityManagerFactory 是标准实现,在所有实现中都是相同的。如果您为任何其他提供商(如 EclipseLink)迁移 ORM,则处理事务的方法不会发生任何变化。相反,如果您使用 hibernate 的会话工厂,它与 hibernate API 绑定,无法迁移到新的供应商。
EntityManager 接口类似于 hibernate 中的 sessionFactory。EntityManager 在 javax.persistance 包下,但 session 和 sessionFactory 在 org.hibernate.Session/sessionFactory 包下。
实体管理器是特定于 JPA 的,而 session/sessionFactory 是特定于休眠的。