Spring embeddeb db table already exists error
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
A "table already exists" error in a Spring application with an embedded database usually means the schema is being initialized more than once. That can happen because schema.sql runs repeatedly, Hibernate is also creating tables, or the database is not as ephemeral as you expected. The fix is usually not complicated, but you need to identify which component is managing schema creation and make that ownership unambiguous.
Understand the Usual Causes
In a typical Spring Boot setup with H2, HSQLDB, or Derby, schema creation may come from more than one place:
- '
schema.sql' - Hibernate DDL generation such as
createorupdate - migration tools such as Flyway or Liquibase
- a persistent file-based embedded database reused across runs
If more than one of these mechanisms tries to create the same table, startup fails with a "table already exists" error.
Pick One Schema Management Strategy
The cleanest rule is simple: one mechanism should own schema creation.
If you use raw SQL scripts:
Then put the schema in schema.sql.
If you want Hibernate to generate the schema during development instead, avoid duplicating the same table creation in schema.sql.
Watch Out for File-Based Embedded Databases
Developers often assume an embedded database is always recreated on each restart. That is true for purely in-memory URLs, but not for file-based ones.
For example, this H2 configuration persists between runs:
If your app creates the schema on the first run and then re-runs schema.sql on the next startup, the table already exists and the second startup fails.
If you really want a fresh database each run for development or tests, use an in-memory database URL instead.
Keep Tests Isolated
This error shows up frequently in tests when the same context or file-backed database is reused across test methods.
A good test setup either:
- uses a fresh in-memory database per test context
- cleans the database before the next test
- uses idempotent schema creation such as
IF NOT EXISTS
For test SQL initialization, idempotent DDL is often the quickest fix.
Flyway and Liquibase Change the Rule
If you use Flyway or Liquibase, those tools should own schema evolution. In that case, avoid having Hibernate or raw startup scripts trying to create the same objects.
For example, with Flyway you would typically:
and let Flyway migrations define the schema.
That way Hibernate checks the schema instead of building it.
Debugging Checklist
When this error appears, check these in order:
- is
schema.sqlcreating the table - is Hibernate also set to create or update tables
- is a migration tool managing the same schema
- is the embedded database file reused across restarts
Once you know which of those are active, the conflict is usually obvious.
Common Pitfalls
The most common mistake is allowing both schema.sql and Hibernate DDL auto-generation to create the same table.
Another issue is assuming an embedded database is always temporary, while the actual JDBC URL points to a file-backed database that persists between runs.
Developers also often fix the symptom with IF NOT EXISTS everywhere without deciding which tool should really own schema evolution. That may hide the duplication instead of simplifying it.
Finally, if Flyway or Liquibase is in use, do not let ad hoc startup scripts compete with your migration history.
Summary
- A "table already exists" error usually means schema creation is happening from more than one place.
- Choose one clear owner for schema creation: SQL scripts, Hibernate, or migrations.
- Distinguish between in-memory embedded databases and file-backed ones.
- Keep tests isolated so initialization does not collide between runs.
- Use idempotent DDL carefully, but solve the ownership conflict instead of only masking it.
Related reading
- Spring Hibernate Query Plan Cache Memory usage
- Spring is losing connection to the DB and does not recover or reconnect
- Spring JPA selecting specific columns
- Spring nested transactions
- Spring Embedded Kafka + Mock Schema Registry State Store ChangeLog Schema not registered
- Spring Expression Language SpEL check empty string?
- Spring Integration Kafka Consumer Listener not Receiving messages
- Spring JPA Repository - Operator SIMPLE_PROPERTY on jsonObject requires a scalar argument

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.