1. 引言

本文将深入探讨 SessionFactoryEntityManagerFactory 的异同点。顾名思义,两者都是用于创建数据库通信对象的工厂类,但它们提供的功能远不止对象创建,还包含丰富的数据库交互特性。

接下来我们将通过对比分析,帮助开发者明确何时选择哪个工厂类更合适。

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 操作支持。

SessionEntityManager 功能相似,负责数据库交互、事务管理和完整的实体生命周期处理。

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 核心异同点

相似之处:

  • ✅ 均支持通过 CriteriaBuilderHibernateCriteriaBuilder 扩展查询能力
  • ✅ 均提供事务管理机制保障数据完整性
  • ⚠️ 创建成本高,需作为单例管理
  • ✅ 线程安全设计支持并发访问

关键差异:

维度 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. 结论

本文通过配置示例和对比分析,揭示了 EntityManagerFactorySessionFactory 的核心差异。两者本质都是为数据库通信创建会话对象的工厂,但 SessionFactory 是 Hibernate 对 JPA 标准的特化实现。

当项目需要:

  • Hibernate 独有功能(如二级缓存)→ 选择 SessionFactory
  • 标准 JPA 实现和厂商中立性 → 选择 EntityManagerFactory

完整代码示例可在 GitHub 获取。


原始标题:EntityManagerFactory vs. SessionFactory | Baeldung