Skip to main content

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:

  1. Object-Relational Mapping (ORM)

    • Java Class ↔ SQL Table
    • Java Attribute ↔ SQL Column
  2. SQL Generation

    • findAll() → SELECT * FROM products
    • save() → INSERT INTO products ...
  3. Schema Management

    • Creation/modification of tables (DDL strategies)

The 5 DDL Strategies​

Overview​

StrategyBehaviorRecommended Usage
noneNo actionProduction (with Flyway/Liquibase)
validateValidates the schema, does not modifyProduction
updateUpdates the schema (adds only)Development
createRecreates the schema at each startupTests
create-dropCreates at startup, drops at shutdownTests

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​

DatabaseHibernate Dialect
PostgreSQLorg.hibernate.dialect.PostgreSQLDialect
MySQL 8+org.hibernate.dialect.MySQL8Dialect
SQL Serverorg.hibernate.dialect.SQLServerDialect
Oracle 12c+org.hibernate.dialect.Oracle12cDialect
H2org.hibernate.dialect.H2Dialect
MariaDBorg.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]

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​

EnvironmentStrategyshow-sql
Developmentupdatetrue
Testscreate-droptrue
Productionvalidate or nonefalse

Next Step​

Now that you master Hibernate, let's move on to Chapter 4 to discover Lombok and reduce boilerplate code!

➡️ Chapter 4: Lombok

⬅️ Previous Chapter: Jakarta vs Javax

⬅️ Back to Module 4