如何避免Spring Boot启动时重复执行data.sql?解决唯一列冲突
哈哈,这个坑我刚入行的时候踩过好几次!每次启动Spring Boot,data.sql里的插入语句碰到唯一约束直接炸,着实烦人。下面给你几个实用的解决办法,还有怎么控制data.sql的执行时机:
1. 调整SQL语句,从根源避免冲突
最直接的方式是修改你的插入语句,让它在数据已存在时跳过或更新,而不是报错:
- MySQL环境:
- 用
INSERT IGNORE:INSERT IGNORE INTO your_table (id, unique_column, content) VALUES (1, 'unique_value', 'test');——如果唯一约束冲突,这条SQL会静默跳过,不会触发报错。 - 用
ON DUPLICATE KEY UPDATE:INSERT INTO your_table (id, unique_column, content) VALUES (1, 'unique_value', 'test') ON DUPLICATE KEY UPDATE content = 'test';——冲突时可以指定更新某些字段,适合需要同步初始数据的场景。
- 用
- PostgreSQL环境:
- 用
ON CONFLICT DO NOTHING:INSERT INTO your_table (unique_column, content) VALUES ('unique_value', 'test') ON CONFLICT (unique_column) DO NOTHING; - 或者
ON CONFLICT DO UPDATE:INSERT INTO your_table (unique_column, content) VALUES ('unique_value', 'test') ON CONFLICT (unique_column) DO UPDATE SET content = 'test';
- 用
2. 配置Spring Boot,控制
data.sql的执行时机 Spring Boot提供了专门的配置项来控制初始化脚本的执行策略,分版本看:
- Spring Boot 2.5+版本:用
spring.sql.init.mode参数:always:每次启动都执行脚本(默认值,这就是你碰到问题的原因)embedded:只在使用嵌入式数据库(比如H2、HSQLDB)时执行,生产环境的外部数据库(MySQL、PostgreSQL)不会触发never:完全禁用初始化脚本执行- 另外还可以搭配
spring.sql.init.continue-on-error=true,让脚本执行时遇到错误继续,但这只是权宜之计,不如前面的SQL调整彻底。
- Spring Boot 2.5之前版本:用
spring.datasource.initialization-mode,参数值和上面一致。
如果是开发环境,你还可以配合JPA的spring.jpa.hibernate.ddl-auto=create-drop,每次启动重建表,这样data.sql执行就不会有冲突,但这个方式只适合开发,绝对不能用在生产环境!
3. 生产环境推荐:用数据库迁移工具
如果是生产环境,强烈建议放弃直接依赖data.sql,改用Flyway或Liquibase这类数据库迁移工具:
- 它们会在数据库中自动创建一张版本记录表,记录已经执行过的脚本。每次启动Spring Boot时,只会执行那些从未运行过的脚本,从根本上杜绝重复执行的问题。
- 你只需要把初始化SQL放到指定目录(比如Flyway的
src/main/resources/db/migration),Spring Boot会自动识别并执行,还能支持脚本版本管理、回滚等高级功能,非常适合生产环境的数据库变更管理。
内容的提问来源于stack exchange,提问作者Imran
相关产品推荐
相关产品推荐

