1. 概述

本文将带你从零开始,手把手配置 Spring 与 JPA,并以 Hibernate 作为持久层实现。如果你已经熟悉 Spring 的基本搭建,可以跳过基础部分;如果不熟,建议先了解 基于 Java 配置的 Spring Web 应用初始化

我们将分两种场景讲解:

✅ Spring Boot 项目中的极简配置
✅ 标准 Spring 项目中的全手动配置(Java + XML)

无论你是想快速上手还是深入理解底层机制,这篇都能覆盖到。


2. Spring Boot 中的 JPA 配置

Spring Boot 的核心理念就是“约定优于配置”,通过 starter 和自动装配机制,把常见的框架集成变得简单粗暴。

2.1 Maven 依赖

要在 Spring Boot 中启用 JPA,只需要引入两个关键依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>3.1.0</version>
</dependency>

⚠️ 注意:

  • spring-boot-starter 提供了自动配置支持
  • spring-boot-starter-data-jpa 会自动拉取 Hibernate、JPA API 等必要依赖,无需手动添加 hibernate-core

2.2 数据源与 JPA 自动配置

Spring Boot 默认使用 Hibernate 作为 JPA 提供者,并且会自动创建 EntityManagerFactoryDataSource,前提是:

✅ 内存数据库(H2、HSQLDB、Derby)

只要 classpath 下有对应驱动,Boot 会自动配置 DataSource

比如使用 H2 数据库,只需加这个依赖:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.1.214</version>
</dependency>

无需任何 Java 或 properties 配置,开箱即用。

❌ 外部数据库(如 MySQL)

需要手动提供数据库连接信息。有两种方式:

方式一:Java 配置类
@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();

    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUsername("mysqluser");
    dataSource.setPassword("mysqlpass");
    dataSource.setUrl(
      "jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true"); 
    
    return dataSource;
}
方式二:application.properties(推荐)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=mysqluser
spring.datasource.password=mysqlpass
spring.datasource.url=jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true

✅ Spring Boot 会自动根据 spring.datasource.* 前缀完成 DataSource 装配。

📌 小贴士:

  • Spring Boot 1.x 使用 Tomcat 连接池
  • Spring Boot 2.x 起默认切换为 HikariCP(性能更强,延迟更低)

更多实战配置示例可查看 GitHub 项目:https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-jpa


3. 非 Boot 项目中使用 Java 配置 JPA

如果你还在维护老项目,或者不想用 Boot,那就得自己动手丰衣足食了。

核心目标是配置三个关键 Bean:

  1. EntityManagerFactory
  2. DataSource
  3. TransactionManager

3.1 配置 EntityManagerFactory

我们使用 LocalContainerEntityManagerFactoryBean —— 它比 LocalEntityManagerFactoryBean 更灵活,支持数据源注入、包扫描、方言设置等。

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig {

   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
      LocalContainerEntityManagerFactoryBean em 
        = new LocalContainerEntityManagerFactoryBean();
      em.setDataSource(dataSource());
      em.setPackagesToScan("com.baeldung.persistence.model");

      JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
      em.setJpaVendorAdapter(vendorAdapter);
      em.setJpaProperties(additionalProperties());

      return em;
   }
   
   // ...
}

📌 关键点说明:

  • packagesToScan: 自动扫描指定包下的 @Entity
  • JpaVendorAdapter: 指定厂商适配器(这里是 Hibernate)
  • jpaProperties: 设置 Hibernate 特有属性

3.2 配置 DataSource

@Bean
public DataSource dataSource(){
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa");
    dataSource.setUsername("tutorialuser");
    dataSource.setPassword("tutorialmy5ql");
    return dataSource;
}

⚠️ 生产环境建议使用连接池(如 HikariCP),而不是 DriverManagerDataSource

3.3 配置事务管理器和异常翻译

@Bean
public PlatformTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
    return new PersistenceExceptionTranslationPostProcessor();
}

@EnableTransactionManagement 启用注解式事务(@Transactional
PersistenceExceptionTranslationPostProcessor 自动将 JPA 异常转为 Spring 的 DataAccessException 层次结构

3.4 Hibernate 属性配置

Properties additionalProperties() {
    Properties properties = new Properties();
    properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
    return properties;
}

常用属性解释:

属性 说明
hibernate.hbm2ddl.auto DDL 模式:create-drop(测试用)、updatevalidate
hibernate.dialect 数据库方言,必须正确匹配数据库类型

4. 使用 XML 配置 JPA(传统方式)

如果你的项目还在用 XML 配置,以下是等效的 beans 定义:

<bean id="myEmf" 
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.baeldung.persistence.model" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        </props>
    </property>
</bean>

<bean id="dataSource" 
  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/spring_jpa" />
    <property name="username" value="tutorialuser" />
    <property name="password" value="tutorialmy5ql" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven />

<bean id="persistenceExceptionTranslationPostProcessor" class=
  "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

⚠️ 注意差异点:

在 Java 配置中,entityManagerFactory() 返回的是 FactoryBean,所以要 .getObject() 获取实际的 EntityManagerFactory 实例:

transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());

而在 XML 中,Spring 容器会自动处理 FactoryBean 的解包,直接 ref="myEmf" 即可。


5. 彻底告别 XML:无 persistence.xml 配置

传统 JPA 要求在 META-INF/persistence.xml 中定义持久化单元,但从 Spring 3.1 开始,这个文件不再是必须的

得益于 LocalContainerEntityManagerFactoryBeanpackagesToScan 支持,我们可以完全用 Java 配置替代 XML。

如何做到?

只需在 factory bean 中设置扫描包路径:

factoryBean.setPackagesToScan("com.example.domain");

Hibernate 会自动发现该包下所有 @Entity 类。

同时,JPA/Hibernate 属性也可以通过代码注入:

factoryBean.setJpaProperties(additionalProperties());

✅ 这意味着:整个项目可以实现 100% Java 配置,零 XML
✅ 特别适合微服务、模块化架构项目


6. Maven 依赖配置(非 Boot 项目)

除了 Spring 核心依赖外,还需显式引入 JPA 实现和数据库驱动:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>6.4.2.Final</version>
</dependency>

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>8.0.19</version>
   <scope>runtime</scope>
</dependency>

📌 说明:

  • hibernate-core 是 JPA 的具体实现
  • mysql-connector-java 是 JDBC 驱动,runtime 范围表示编译时不需直接依赖
  • 可替换为其他数据库驱动(PostgreSQL、Oracle 等),只要 Hibernate 支持即可

详细依赖可参考:Spring Maven 教程


7. 总结

本文系统梳理了在 Spring 生态中集成 JPA 的两种主流方式:

场景 配置方式 推荐程度
Spring Boot 项目 Starter + 自动装配 ✅ 强烈推荐
传统 Spring 项目 Java 配置 or XML ⚠️ 维护老项目时使用

关键结论:

  • ✅ Spring Boot 极大简化了 JPA 集成,三步搞定:加依赖、配数据源、写实体
  • ✅ 非 Boot 项目需手动配置 EntityManagerFactoryDataSourceTransactionManager
  • ✅ 自 Spring 3.1 起,persistence.xml 已可被完全替代
  • ✅ 推荐使用 Java 配置取代 XML,更易维护、类型安全

所有示例代码均已上传至 GitHub:
👉 https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-jpa-2

踩坑提示:
⚠️ 记得开启 @EnableTransactionManagement,否则 @Transactional 不生效
⚠️ 实体类包路径要被正确扫描到,否则报 No EntityManager bound 错误
⚠️ 生产环境禁用 hbm2ddl.auto=create-drop,防止数据丢失

搞定!收工。


原始标题:A Guide to JPA with Spring