1. 引言
本文将深入探讨 SessionFactory 和 EntityManagerFactory 的异同点。顾名思义,两者都是用于创建数据库通信对象的工厂类,但它们提供的功能远不止对象创建,还包含丰富的数据库交互特性。
接下来我们将通过对比分析,帮助开发者明确何时选择哪个工厂类更合适。
2. 什么是 EntityManagerFactory?
Java Persistence API (JPA) 是 Java 应用中管理持久化数据的规范,提供了标准化的关系型数据库交互方式。作为 JPA 核心接口,EntityManager 负责与持久化上下文交互并管理实体生命周期,提供轻量级实例支持基础 CRUD 操作。
实际开发中频繁需要 EntityManager 实例,这时 EntityManagerFactory 就派上用场了。EntityManagerFactory 是 JPA 接口,用于创建 EntityManager 实例,以线程安全方式实现持久化上下文交互。
2.1 配置过程
首先定义实体类:
@Entity(name = "persons")
public class Person {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
private String name;
private String email;
// 省略 getter/setter
}
配置方式多样,这里采用 persistence.xml 方案。在 resource/META-INF 目录创建配置文件:
<persistence-unit name="com.baeldung.sfvsemf.persistence_unit" transaction-type="RESOURCE_LOCAL">
<description>Persistence Unit for SessionFactory vs EntityManagerFactory code example</description>
<class>com.baeldung.sfvsemf.entity.Person</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.generate_statistics" value="false"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:db2;DB_CLOSE_DELAY=-1"/>
<property name="jakarta.persistence.jdbc.user" value="sa"/>
<property name="jakarta.persistence.jdbc.password" value=""/>
</properties>
</persistence-unit>
⚠️ 示例使用 H2 内存数据库,但实际支持主流关系型数据库,只需确保方言和驱动类配置正确。
2.2 使用示例
配置完成后,使用 EntityManagerFactory 创建 EntityManager 对象非常简单。但要注意:EntityManagerFactory 创建成本高昂,资源消耗大,强烈建议实现为单例模式。
下面通过基础操作演示用法(为简化示例未实现单例):
@Test
public void givenEntityManagerFactory_whenPersistAndFind_thenAssertObjectPersisted() {
EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("com.baeldung.sfvsemf.persistence_unit");
EntityManager entityManager = entityManagerFactory.createEntityManager();
try {
entityManager.getTransaction().begin();
Person person = new Person("John", "john@example.com");
entityManager.persist(person);
entityManager.getTransaction().commit();
Person persistedPerson = entityManager.find(Person.class, person.getId());
assertEquals(person.getName(), persistedPerson.getName());
assertEquals(person.getEmail(), persistedPerson.getEmail());
} catch (Exception ex) {
entityManager.getTransaction().rollback();
} finally {
entityManager.close();
entityManagerFactory.close();
}
}
3. 什么是 SessionFactory?
作为主流 ORM 框架,Hibernate 使用 SessionFactory 创建和管理 Session 实例。与 EntityManagerFactory 类似,SessionFactory 同样提供线程安全的数据库连接和 CRUD 操作支持。
Session 与 EntityManager 功能相似,负责数据库交互、事务管理和完整的实体生命周期处理。
3.1 配置过程
假设读者已具备 Hibernate 基础配置知识(详细内容可参考Hibernate 系列文章)。沿用前文的实体类,在 resources 目录添加 hibernate.cfg.xml:
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.h2.Driver</property>
<property name="hibernate.connection.url">jdbc:h2:mem:db2;DB_CLOSE_DELAY=-1</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.baeldung.sfvsemf.entity.Person"/>
</session-factory>
</hibernate-configuration>
3.2 使用示例
与 EntityManagerFactory 一样,SessionFactory 创建成本高,建议作为单例使用。 配置完成后,通过以下方式执行基础操作:
@Test
void givenSessionFactory_whenPersistAndFind_thenAssertObjectPersisted() {
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
Person person = new Person("John", "john@example.com");
session.persist(person);
transaction.commit();
Person persistedPerson = session.find(Person.class, person.getId());
assertEquals(person.getName(), persistedPerson.getName());
assertEquals(person.getEmail(), persistedPerson.getEmail());
} catch (Exception ex) {
if (transaction != null) {
transaction.rollback();
}
} finally {
session.close();
sessionFactory.close();
}
}
4. EntityManagerFactory 与 SessionFactory 对比
两者核心功能相似,但存在关键差异。下面从多个维度进行对比分析:
4.1 核心异同点
相似之处:
- ✅ 均支持通过 CriteriaBuilder 和 HibernateCriteriaBuilder 扩展查询能力
- ✅ 均提供事务管理机制保障数据完整性
- ⚠️ 创建成本高,需作为单例管理
- ✅ 线程安全设计支持并发访问
关键差异:
维度 | EntityManagerFactory | SessionFactory |
---|---|---|
标准化程度 | JPA 规范标准接口 | Hibernate 特有实现 |
缓存机制 | 仅支持一级缓存 | 支持一级和二级缓存 |
查询语言 | 仅支持 JPQL | 同时支持 JPQL 和 HQL |
框架耦合度 | 厂商中立,兼容所有 JPA 实现 | 仅限 Hibernate 生态 |
核心差异点: SessionFactory 实际继承自 EntityManagerFactory,但 二级缓存是 Hibernate 独有特性,在 SessionFactory 级别实现跨会话数据共享,JPA 规范未包含此功能。
4.2 使用场景对比
选择建议:
✅ 优先 EntityManagerFactory 的场景:
- 需要厂商无关性(可随时切换 Hibernate/EclipseLink/OpenJPA 等实现)
- 项目遵循 JPA 标准规范
- 不依赖 Hibernate 特有功能
✅ 优先 SessionFactory 的场景:
- 明确使用 Hibernate 技术栈
- 需要二级缓存提升性能
- 依赖 Hibernate 特有功能(如批量查询、HQL 增强语法等)
简单粗暴总结: EntityManagerFactory 胜在灵活性和可移植性,SessionFactory 胜在 Hibernate 生态深度集成。
5. 结论
本文通过配置示例和对比分析,揭示了 EntityManagerFactory 和 SessionFactory 的核心差异。两者本质都是为数据库通信创建会话对象的工厂,但 SessionFactory 是 Hibernate 对 JPA 标准的特化实现。
当项目需要:
- Hibernate 独有功能(如二级缓存)→ 选择 SessionFactory
- 标准 JPA 实现和厂商中立性 → 选择 EntityManagerFactory
完整代码示例可在 GitHub 获取。