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 提供者,并且会自动创建 EntityManagerFactory
和 DataSource
,前提是:
✅ 内存数据库(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:
EntityManagerFactory
DataSource
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 (测试用)、update 、validate |
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 开始,这个文件不再是必须的。
得益于 LocalContainerEntityManagerFactoryBean
的 packagesToScan
支持,我们可以完全用 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 项目需手动配置
EntityManagerFactory
、DataSource
、TransactionManager
- ✅ 自 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
,防止数据丢失
搞定!收工。