Spring Boot Data JPA with H2 and data.sql - Table not Found
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
This error usually means Spring Boot tried to run data.sql before the table existed. With H2 and Spring Data JPA, that often happens because Hibernate is expected to create the schema, but SQL initialization runs earlier in the startup sequence unless you configure it explicitly.
Why the Table Is Missing
There are two common ways tables get created at startup:
- Hibernate creates them from your JPA entities
- '
schema.sqlcreates them with explicit DDL'
data.sql only inserts data. If Spring executes data.sql before either of those schema creation steps has produced the table, H2 throws a "table not found" error.
This is why the exact initialization order matters more than the database engine itself.
The Most Common JPA-Based Fix
If you want Hibernate to create the tables from your entities and then load data.sql, enable deferred data-source initialization:
That tells Spring Boot to let JPA schema creation happen before the SQL data script runs.
A minimal entity might look like this:
Then data.sql can safely reference the generated table:
The Script-Driven Alternative
If you prefer explicit SQL over JPA-generated schema, use schema.sql and data.sql together:
With that approach, schema.sql creates the table and data.sql fills it. This avoids depending on Hibernate DDL generation, which can be useful for predictable tests.
When spring.sql.init.mode Matters
For an embedded H2 database, Spring Boot usually initializes SQL scripts automatically. For non-embedded databases, you may need:
That property does not solve the table-order problem by itself, but it does control whether SQL initialization runs at all.
Prefer One Initialization Strategy
The cleanest setup uses one main schema strategy:
- JPA/Hibernate for quick test environments
- '
schema.sqlplusdata.sqlfor explicit SQL-managed test setup' - Flyway or Liquibase for real migration-driven applications
Mixing several initialization systems can work, but it becomes harder to reason about startup order and harder to debug when tables appear twice or not at all.
A Small Repository Test Example
This kind of test quickly reveals whether your startup initialization order is correct.
Common Pitfalls
The biggest mistake is expecting data.sql to create tables. It only inserts rows; it does not define the schema.
Another common issue is relying on Hibernate DDL generation without setting spring.jpa.defer-datasource-initialization=true. In that case, data.sql can run too early.
A third mistake is mixing Flyway or Liquibase with ad hoc schema.sql and data.sql scripts without a clear reason. That makes startup behavior harder to predict.
Summary
- "Table not found" usually means
data.sqlran before the schema existed. - If Hibernate creates the schema, use
spring.jpa.defer-datasource-initialization=true. - If SQL scripts create the schema, put DDL in
schema.sqland inserts indata.sql. - '
spring.sql.init.mode=alwayscontrols whether SQL initialization runs, especially for non-embedded databases.' - Prefer one clear database initialization strategy instead of mixing several by accident.
Related reading
- Spring Boot. DataJpaTest H2 embedded database create schema
- Spring boot ddl auto generator
- Spring Boot default H2 jdbc connection and H2 console
- Spring boot doesn't load data to initialize database using data.sql
- Spring Boot default proxying mechanism
- Spring Boot default test throws an IllegalStateException
- Spring boot fails to load DataSource using PostgreSQL driver
- Spring Boot Getting Scheduled cron value from database

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack 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.