Spring Boot集成Liquibase后仍执行data.sql报错问题咨询
Hey, great question—Liquibase absolutely solves this problem, and it's exactly what it's designed for. Let's walk through how to fix your current issue and get the behavior you want (run initial data once, skip on subsequent starts):
First, fix the root cause: Disable Spring Boot's automatic data.sql execution
The reason your data.sql is still running every time is that Spring Boot's default behavior is to execute data.sql on every startup, regardless of Liquibase being present. You need to turn this off:
- For Spring Boot 2.5+, add this to your
application.propertiesorapplication.yaml:spring.sql.init.mode=never - For older Spring Boot versions, use:
spring.datasource.initialization-mode=never
This stops Spring from running your data.sql automatically, leaving Liquibase in full control of database initialization.
Migrate your data.sql logic to a Liquibase ChangeSet
Liquibase tracks every database change in a databasechangelog table (it creates this table automatically on first run). Each change is wrapped in a ChangeSet—a uniquely identified block of logic that only runs once. Here's how to reuse your existing data.sql:
- Create a Liquibase master changelog file (default path is
src/main/resources/db/changelog/db.changelog-master.yaml—you can use XML, SQL, or JSON too, but YAML is clean for this use case). - Add a ChangeSet that references your
data.sqlfile. Example content:databaseChangeLog: - changeSet: id: "initial-data-setup-1.0" author: "your-name" # Replace with your name/team changes: - sqlFile: path: classpath:/data.sql relativeToChangelogFile: false encoding: UTF-8- The
idandauthorcombination must be unique—this is how Liquibase tracks which ChangeSets have run. pathpoints to your existingdata.sqlin the classpath.
- The
Key Liquibase configurations to verify
- Dependency: Make sure you have the Spring Boot Liquibase starter in your build file:
- For Maven (pom.xml):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-liquibase</artifactId> </dependency> - For Gradle (build.gradle):
implementation 'org.springframework.boot:spring-boot-starter-liquibase'
- For Maven (pom.xml):
- Changelog path: If you placed your master changelog in a non-default location, configure it:
spring.liquibase.change-log=classpath:/custom/path/db.changelog-master.yaml - Preconditions (optional but safe): If you want extra safeguards (e.g., only run the SQL if a table exists, or if data isn't already present), add preconditions to your ChangeSet:
This ensures the ChangeSet only runs if the target table doesn't exist (adjust based on your needs).databaseChangeLog: - changeSet: id: "initial-data-setup-1.0" author: "your-name" preConditions: - not: - tableExists: tableName: your_table_name changes: - sqlFile: path: classpath:/data.sql relativeToChangelogFile: false
Handling existing data (if you already ran data.sql manually)
If you previously ran data.sql via Spring Boot, Liquibase will try to run it again on first startup, causing duplicate data errors. To fix this:
- Either manually insert a record into the
databasechangelogtable for your ChangeSet (matching theidandauthoryou set), or - Use the Liquibase CLI command
liquibase markNextChangeSetRanto mark the ChangeSet as executed.
Final Result
Once set up, here's what happens:
- On first startup: Liquibase creates its tracking tables, runs your
data.sqlvia the ChangeSet, and logs the execution indatabasechangelog. - On subsequent startups: Liquibase checks
databasechangelog, sees the ChangeSet already ran, and skips it entirely—no more duplicate data errors!
内容的提问来源于stack exchange,提问作者Imran

