Spring Boot
data.sql
database initialization
troubleshooting
application configuration

Spring boot doesn't load data to initialize database using data.sql

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When data.sql is ignored in a Spring Boot application, the root cause is usually startup order, not the SQL file itself. Spring Boot only runs initialization scripts under specific conditions, and those conditions changed across recent Spring Boot releases.

How data.sql Is Supposed To Run

Spring Boot can initialize a database from SQL scripts placed in src/main/resources. The common convention is:

  • 'schema.sql creates tables'
  • 'data.sql inserts rows'

For an embedded database such as H2, this often works with no extra settings. For an external database such as PostgreSQL or MySQL, Boot may skip initialization unless you opt in.

A minimal example looks like this:

properties
1spring.datasource.url=jdbc:h2:mem:testdb
2spring.datasource.driver-class-name=org.h2.Driver
3spring.datasource.username=sa
4spring.datasource.password=
5spring.h2.console.enabled=true
6spring.sql.init.mode=always
7spring.jpa.defer-datasource-initialization=true

And then:

sql
-- src/main/resources/data.sql
insert into users(id, username) values (1, 'alice');
insert into users(id, username) values (2, 'bob');

If the application starts and the table exists before the script runs, the rows should be inserted automatically.

The Most Common Cause: JPA Creates Tables Too Late

A frequent failure mode appears when Hibernate generates the schema, but data.sql runs before Hibernate has created the tables. In that case the inserts fail silently in logs you may not be watching, or the application aborts during startup.

For Spring Boot 2.5 and later, the usual fix is:

properties
spring.jpa.defer-datasource-initialization=true

That property tells Boot to wait until JPA has finished schema creation before running data.sql.

If you also want Hibernate to create the schema automatically in development, pair it with a JPA setting like this:

properties
spring.jpa.hibernate.ddl-auto=create
spring.jpa.defer-datasource-initialization=true
spring.sql.init.mode=always

Without the defer setting, data.sql may target tables that do not exist yet.

External Databases Need Explicit Initialization

Another common confusion is that Boot behaves differently for embedded and non-embedded databases. H2 and HSQLDB are often initialized by default during local development, but PostgreSQL and MySQL typically require this:

properties
spring.sql.init.mode=always

If you leave the default behavior in place, Boot may decide not to run data.sql at all. That makes the application look like it ignored the script even though the framework was following its initialization rules.

Verify File Placement And Naming

The SQL files must be on the application classpath. The standard location is:

text
src/main/resources/data.sql
src/main/resources/schema.sql

Small mistakes matter here:

  • 'Data.sql instead of data.sql'
  • placing the file in src/test/resources
  • putting it in a nested directory without configuring a custom location

If you want a custom script location, declare it explicitly:

properties
spring.sql.init.data-locations=classpath:/db/init-data.sql
spring.sql.init.schema-locations=classpath:/db/init-schema.sql

Watch Out For Flyway And Liquibase

If your application uses Flyway or Liquibase, those tools usually become the source of truth for schema and seed data. Mixing them casually with schema.sql and data.sql can produce confusing startup order or duplicated inserts.

A cleaner rule is:

  • use schema.sql and data.sql for small local setups
  • use Flyway or Liquibase for versioned schema changes in real deployments

If Flyway is active, seed data is usually better placed in a migration such as V2__seed_users.sql rather than in data.sql.

A Small End-To-End Example

Here is a minimal entity and repository-backed setup that works with H2.

java
1import jakarta.persistence.Entity;
2import jakarta.persistence.Id;
3
4@Entity
5public class UserAccount {
6    @Id
7    private Long id;
8    private String username;
9
10    protected UserAccount() {
11    }
12
13    public UserAccount(Long id, String username) {
14        this.id = id;
15        this.username = username;
16    }
17}
sql
1create table user_account (
2    id bigint primary key,
3    username varchar(100) not null
4);
5
6insert into user_account(id, username) values (1, 'alice');
7insert into user_account(id, username) values (2, 'bob');

In this arrangement, schema.sql creates the table and data.sql inserts rows. That is usually simpler than asking Hibernate to create the table unless you specifically want JPA-driven schema generation.

How To Debug It Quickly

Enable SQL initialization logs so you can see whether Spring Boot found and executed the script:

properties
logging.level.org.springframework.jdbc.datasource.init=DEBUG
logging.level.org.springframework.boot.sql.init=DEBUG

If Boot logs that it skipped initialization, the problem is configuration. If it logs SQL errors, the file was found and the problem is schema mismatch or ordering.

Common Pitfalls

  • Expecting data.sql to run against PostgreSQL or MySQL without spring.sql.init.mode=always.
  • Letting Hibernate create tables but forgetting spring.jpa.defer-datasource-initialization=true.
  • Placing data.sql outside src/main/resources.
  • Using table names in data.sql that do not match the actual generated schema.
  • Mixing Flyway or Liquibase with Boot SQL initialization without a clear ownership rule.

Summary

  • 'data.sql problems are usually caused by initialization order or Boot configuration.'
  • For external databases, set spring.sql.init.mode=always.
  • If JPA creates tables, add spring.jpa.defer-datasource-initialization=true.
  • Keep data.sql on the classpath and confirm the file name exactly.
  • Turn on SQL init debug logging to distinguish a skipped script from a failing script.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.