Skillversitas

H2 Database

H2 In-Memory Database

H2 is a lightweight embedded database that runs in memory. It's ideal for:

  • Development — no need to install an external database
  • Testing — every test starts from a clean state
  • Prototyping — build and run the application quickly

H2 supports in-memory mode and file-based mode. For Spring Boot, we focus on in-memory mode.

Configuration in application.properties

Add the dependency in pom.xml:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

Configuration in application.properties:

# H2 Database
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

# H2 Console
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

# JPA / Hibernate
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true

Property explanation:

Property Value Description
spring.datasource.url jdbc:h2:mem:testdb In-memory database named testdb
spring.h2.console.enabled true Enable the web console
spring.h2.console.path /h2-console Path to access the console
spring.jpa.hibernate.ddl-auto create-drop Create the schema at startup, drop it at shutdown
spring.jpa.show-sql true Log SQL to the console

H2 Console

Once the application is running, open the H2 Console in your browser:

http://localhost:8080/h2-console

On the H2 Console login page:

  1. JDBC URL: jdbc:h2:mem:testdb
  2. User Name: sa
  3. Password: (empty)
  4. Click Connect

You can run SQL directly in the console:

SELECT * FROM users;
INSERT INTO users (name, email) VALUES ('John', '[email protected]');
SHOW TABLES;

data.sql for Seed Data

Spring Boot automatically runs data.sql at startup if the file exists on the classpath:

-- data.sql (in src/main/resources/)
INSERT INTO users (name, email, created_at) VALUES
('Mike', '[email protected]', CURRENT_TIMESTAMP),
('John', '[email protected]', CURRENT_TIMESTAMP),
('Anna', '[email protected]', CURRENT_TIMESTAMP);

INSERT INTO products (name, price, stock) VALUES
('Laptop', 12000000, 10),
('Mouse', 150000, 50),
('Keyboard', 350000, 30);

Execution order: schema.sql → data.sql

-- schema.sql (optional, Hibernate usually handles this)
CREATE TABLE IF NOT EXISTS users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Spring Boot DevTools + H2

DevTools provides an automatic restart when the code changes:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

When using H2 in-memory + DevTools, you need to be careful:

# So H2 isn't reset when devtools triggers a restart
spring.h2.console.enabled=true

# or disable devtools restart for certain classes
spring.devtools.restart.exclude=static/**,public/**

Configuration for Testing

Use a separate profile for tests:

# application-test.properties
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
spring.jpa.hibernate.ddl-auto=create-drop
spring.h2.console.enabled=false
@SpringBootTest
@ActiveProfiles("test")
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void shouldSaveUser() {
        User user = new User();
        user.setName("Test User");
        user.setEmail("[email protected]");

        User saved = userRepository.save(user);

        assertThat(saved.getId()).isNotNull();
        assertThat(saved.getName()).isEqualTo("Test User");
    }
}

H2 for Development vs Production

┌─────────────────────┬──────────────┬──────────────────┐
│ Aspect              │ H2 In-Memory │ MySQL/PostgreSQL │
├─────────────────────┼──────────────┼──────────────────┤
│ Setup Speed         │ Instant      │ Requires install │
│ Performance         │ Adequate     │ Better           │
│ Persistence         │ Lost on      │ Persistent       │
│                     │ restart      │                  │
│ SQL Features        │ Basic        │ Full             │
│ Best For            │ Dev/Test     │ Production       │
│ Concurrent Access   │ Limited      │ Full             │
└─────────────────────┴──────────────┴──────────────────┘

H2 is very helpful during development and testing. But for production, you need a real database. In the next chapter, we'll configure MySQL and PostgreSQL for production.