Spring Boot如何正确配置PostgreSQL通过schema.sql和data.sql初始化数据?
Spring Boot + PostgreSQL 启动时自动初始化表结构与数据的正确配置
问题描述
我正在开发一个使用PostgreSQL的Spring Boot项目,希望应用启动时自动创建表并插入初始数据。
当前application.properties配置:
spring.datasource.url=jdbc:postgresql://localhost:5432/progra3db spring.datasource.username=progra3 spring.datasource.password=progra3 spring.datasource.driver-class-name=org.postgresql.Driver spring.sql.init.mode=always spring.jpa.hibernate.ddl-auto=none spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true
schema.sql表定义:
CREATE TABLE IF NOT EXISTS nodes ( id BIGINT PRIMARY KEY, code VARCHAR(50), name VARCHAR(100), type VARCHAR(50), description TEXT, parent_id BIGINT );
data.sql测试数据:
INSERT INTO nodes (id, code, name, type, description, parent_id) VALUES (1, '1', 'Assets', 'GROUP', 'Company assets', NULL), (2, '1.1', 'Current Assets', 'GROUP', 'Short-term assets', 1), (3, '1.1.1', 'Cash', 'ACCOUNT', 'Cash available', 2);
启动应用后项目可运行,但有时数据未插入或表未按预期创建。尝试修改spring.jpa.hibernate.ddl-auto为none、update和create,仍不清楚使用schema.sql和data.sql时的正确配置方式。
正确配置方案
1. 调整核心配置项
更新application.properties为如下配置:
# 数据源基础配置 spring.datasource.url=jdbc:postgresql://localhost:5432/progra3db spring.datasource.username=progra3 spring.datasource.password=progra3 spring.datasource.driver-class-name=org.postgresql.Driver # SQL初始化核心配置 spring.sql.init.mode=always # 默认扫描classpath下的schema.sql和data.sql,自定义路径可取消下方注释配置 # spring.sql.init.schema-locations=classpath:schema.sql # spring.sql.init.data-locations=classpath:data.sql # JPA/Hibernate配置 spring.jpa.hibernate.ddl-auto=none spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true # 关键:延迟JPA初始化,避免与SQL脚本执行顺序冲突 spring.jpa.defer-datasource-initialization=true
2. 配置关键说明
spring.sql.init.mode=always:强制应用启动时执行schema.sql和data.sql,无论数据库是否已有数据或表结构。若仅需首次初始化,可改为embedded(仅针对嵌入式数据库)。spring.jpa.hibernate.ddl-auto=none:完全禁用Hibernate的自动DDL生成,避免其与自定义schema.sql的表结构定义冲突。spring.jpa.defer-datasource-initialization=true:解决执行顺序问题——Spring Boot默认先初始化JPA,再执行SQL脚本,会导致Hibernate尝试映射实体时表尚未创建。开启该配置后,会先执行SQL初始化脚本,再初始化JPA,确保表创建完成后再处理数据插入和实体映射。
3. 额外注意事项
- SQL文件位置:确保
schema.sql和data.sql放在src/main/resources目录下,这是Spring Boot默认扫描路径。若文件路径不同,需通过spring.sql.init.schema-locations和spring.sql.init.data-locations指定。 - 表创建的幂等性:你的
schema.sql已使用CREATE TABLE IF NOT EXISTS,可避免重复创建表时的报错,保持该写法即可。 - 数据插入的幂等性:当前
INSERT语句在表已有数据时会因主键冲突报错。如需重复启动时不报错,可修改为幂等插入:
INSERT INTO nodes (id, code, name, type, description, parent_id) VALUES (1, '1', 'Assets', 'GROUP', 'Company assets', NULL), (2, '1.1', 'Current Assets', 'GROUP', 'Short-term assets', 1), (3, '1.1.1', 'Cash', 'ACCOUNT', 'Cash available', 2) ON CONFLICT (id) DO NOTHING;
内容的提问来源于stack exchange,提问作者Angello Escobar




