Chapter 3: Hibernate and DDL Strategies
Introduction
Question: How does Hibernate create tables in your database?
Answer: Through DDL strategies (Data Definition Language).
In this chapter, you will understand:
- What Hibernate is
- The 5 DDL strategies (
none,validate,update,create,create-drop) - When to use each strategy
- How to configure Hibernate for PostgreSQL
What is Hibernate?
Definition
Hibernate is the implementation of JPA (Java Persistence API) used by Spring Boot.
Analogy:
- JPA = Interface (the "what") 📄
- Hibernate = Implementation (the "how") ⚙️
Example:
// JPA defines the interface
@Entity
public class Product { ... }
// Hibernate implements the mapping
// Automatically generates SQL
Role of Hibernate
Hibernate automatically manages:
-
Object-Relational Mapping (ORM)
- Java Class ↔ SQL Table
- Java Attribute ↔ SQL Column
-
SQL Generation
findAll()→SELECT * FROM productssave()→INSERT INTO products ...
-
Schema Management
- Creation/modification of tables (DDL strategies)
The 5 DDL Strategies
Overview
| Strategy | Behavior | Recommended Usage |
|---|---|---|
| none | No action | Production (with Flyway/Liquibase) |
| validate | Validates the schema, does not modify | Production |
| update | Updates the schema (adds only) | Development |
| create | Recreates the schema at each startup | Tests |
| create-drop | Creates at startup, drops at shutdown | Tests |
1. ddl-auto: none
Behavior: Hibernate does not touch the database.
When to use it: In production with migration tools (Flyway, Liquibase).
Configuration:
spring:
jpa:
hibernate:
ddl-auto: none
Example:
Application startup...
→ Hibernate does not create/modify any tables
→ Tables must already exist
Advantages:
- ✅ Full control over the schema
- ✅ No surprises in production
Disadvantages:
- ❌ You must manage migrations manually
2. ddl-auto: validate
Behavior: Hibernate validates that the schema matches the entities but does not modify it.
When to use it: In production to check consistency.
Configuration:
spring:
jpa:
hibernate:
ddl-auto: validate
Example:
Application startup...
→ Hibernate compares entities with tables
→ If difference → ERROR and stop
Typical error:
Schema-validation: missing column [price] in table [products]
Advantages:
- ✅ Detects inconsistencies
- ✅ Secures startup
Disadvantages:
- ❌ Does not automatically fix
3. ddl-auto: update
Behavior: Hibernate updates the schema (adds columns/tables but never deletes).
When to use it: In development.
Configuration:
spring:
jpa:
hibernate:
ddl-auto: update
Example:
Initial Entity:
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
}
Database:
CREATE TABLE products (
id BIGINT PRIMARY KEY,
name VARCHAR(255)
);
Entity Modification:
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
private Double price; // NEW
}
Application Startup:
ALTER TABLE products ADD COLUMN price DOUBLE PRECISION;
✅ Column added automatically!
Advantages:
- ✅ Convenient in development
- ✅ No need to manage the schema manually
Disadvantages:
- ❌ Does not remove obsolete columns
- ❌ Can cause long-term inconsistencies
- ❌ DANGEROUS in production
4. ddl-auto: create
Behavior: Hibernate recreates all tables at each startup (drops and recreates).
When to use it: For automated tests.
Configuration:
spring:
jpa:
hibernate:
ddl-auto: create
Example:
Application startup...
→ DROP TABLE products;
→ CREATE TABLE products (...);
→ All data is LOST
Advantages:
- ✅ Always clean schema
- ✅ Ideal for tests
Disadvantages:
- ❌ TOTAL DATA LOSS at each startup
- ❌ NEVER USE IN PRODUCTION
5. ddl-auto: create-drop
Behavior: Like create, but also drops tables at application shutdown.
When to use it: For unit/integration tests.
Configuration:
spring:
jpa:
hibernate:
ddl-auto: create-drop
Example:
Application startup...
→ DROP TABLE products;
→ CREATE TABLE products (...);
... tests ...
Application shutdown...
→ DROP TABLE products;
Advantages:
- ✅ Clean test environment
- ✅ No residual data
Disadvantages:
- ❌ TOTAL DATA LOSS
- ❌ NEVER USE IN PRODUCTION
Complete Configuration for PostgreSQL
Development Configuration
File: application-dev.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/dev_db
username: postgres
password: ${DB_PASSWORD}
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update # Convenient in dev
show-sql: true # See queries
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true # Format SQL
Production Configuration
File: application-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-server:5432/prod_db
username: prod_user
password: ${DB_PASSWORD}
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: validate # Validation only
show-sql: false # No SQL logs in prod
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
Test Configuration
File: application-test.yml
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop # Cleans after each test
show-sql: true
Hibernate Dialects
What is a Dialect?
A dialect is Hibernate's adaptation to a specific database.
Analogy: Like regional dialects of a language (French from France vs. French from Quebec).
Common Dialects
| Database | Hibernate Dialect |
|---|---|
| PostgreSQL | org.hibernate.dialect.PostgreSQLDialect |
| MySQL 8+ | org.hibernate.dialect.MySQL8Dialect |
| SQL Server | org.hibernate.dialect.SQLServerDialect |
| Oracle 12c+ | org.hibernate.dialect.Oracle12cDialect |
| H2 | org.hibernate.dialect.H2Dialect |
| MariaDB | org.hibernate.dialect.MariaDBDialect |
Why Specify a Dialect?
Example: Auto-increment ID generation
PostgreSQL:
CREATE TABLE products (
id BIGSERIAL PRIMARY KEY, -- PostgreSQL
name VARCHAR(255)
);
MySQL:
CREATE TABLE products (
id BIGINT AUTO_INCREMENT PRIMARY KEY, -- MySQL
name VARCHAR(255)
);
Without dialect: Hibernate does not know which syntax to use.
With dialect: Hibernate generates the correct SQL for your database.
SQL Logs and Debugging
Display SQL Queries
Configuration:
spring:
jpa:
show-sql: true # Enable SQL logs
properties:
hibernate:
format_sql: true # Format SQL for readability
Console:
Hibernate:
insert
into
products
(name, price, id)
values
(?, ?, ?)
Display Parameter Values
Configuration:
logging:
level:
org.hibernate.SQL: DEBUG # SQL logs
org.hibernate.type.descriptor.sql.BasicBinder: TRACE # Parameter values
Console:
Hibernate:
insert
into
products
(name, price, id)
values
(?, ?, ?)
binding parameter [1] as [VARCHAR] - [Laptop]
binding parameter [2] as [DOUBLE] - [999.99]
binding parameter [3] as [BIGINT] - [1]
Recommended Strategies
Visual Summary
Development
↓
ddl-auto: update
show-sql: true
↓
Quick changes
Tables created automatically
---
Tests
↓
ddl-auto: create-drop
show-sql: true
↓
Clean environment
Data erased after tests
---
Production
↓
ddl-auto: validate (or none)
show-sql: false
↓
No automatic modification
Migrations managed by Flyway/Liquibase
Common Errors
Error 1: Table Doesn't Exist
Error:
Table "products" doesn't exist
Cause: ddl-auto: none or validate, but tables do not exist.
Solution: Use ddl-auto: update or create tables manually.
Error 2: Schema Mismatch
Error:
Schema-validation: missing column [price] in table [products]
Cause: ddl-auto: validate, but the entity and table differ.
Solution:
- Temporarily switch to
update - Or modify the table manually
Error 3: Data Lost After Restart
Error: All my data disappears on restart!
Cause: ddl-auto: create or create-drop.
Solution: Switch to update or validate.
Summary
Key Points
✅ Hibernate = JPA Implementation
✅ 5 DDL strategies: none, validate, update, create, create-drop
✅ Development: update
✅ Production: validate or none + Flyway
✅ Tests: create-drop
✅ Dialect: Adapts Hibernate to your database
DDL Strategies Checklist
| Environment | Strategy | show-sql |
|---|---|---|
| Development | update | true |
| Tests | create-drop | true |
| Production | validate or none | false |
Next Step
Now that you master Hibernate, let's move on to Chapter 4 to discover Lombok and reduce boilerplate code!