Spring Boot: H2 In-Memory Database
H2 is a lightweight Java SQL database that Spring Boot auto-configures when it finds the H2 dependency on the classpath. It runs entirely in memory by default, no installation needed, making it ideal for development, tests, and prototyping. Data is lost when the application stops unless persistent mode is configured.
Contents
Adding H2 Dependency
H2 provides the in-memory database, and Spring Data JPA the repositories.
<!-- Maven — typically test scope for production projects, or compile for dev -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Also add Spring Data JPA if using JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Auto-Configuration
When Spring Boot detects H2 on the classpath and no other DataSource
- An in-memory H2
with a random database name.DataSource - Spring Data JPA / Hibernate with
: tables are created on startup and dropped on shutdown.ddl-auto=create-drop - The H2 console at
(disabled by default: must be enabled in properties)./h2-console
H2 Console Setup
Turn on the H2 console for development with these properties.
# application.properties
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# set to true only if you need remote access
spring.h2.console.settings.web-allow-others=false
Open the H2 console at http://localhost:8080/h2-consolejdbc:h2:mem:testdb
.requestMatchers("/h2-console/**").permitAll().headers(h -> h.frameOptions(f -> f.disable()))application.properties Config
The settings below can be placed in application.ymlapplication.properties
# Fix the database name so the H2 console JDBC URL is predictable
spring.datasource.url=jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# JPA / Hibernate
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop # or update, validate, none
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
DB_CLOSE_DELAY=-1Using with Spring Data JPA (Entity + Repository)
An entity and a repository are all you need to store data in H2.
import jakarta.persistence.*;
@Entity
@Table(name = "products")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private BigDecimal price;
// constructors, getters, setters
}
import org.springframework.data.jpa.repository.JpaRepository;
import java.math.BigDecimal;
import java.util.List;
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findByPriceGreaterThan(BigDecimal minPrice);
List<Product> findByNameContainingIgnoreCase(String keyword);
}
Schema and Data SQL Files
Place SQL files in src/main/resources
-- src/main/resources/schema.sql
CREATE TABLE IF NOT EXISTS products (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(200) NOT NULL,
price DECIMAL(10, 2) NOT NULL
);
CREATE TABLE IF NOT EXISTS orders (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
product_id BIGINT NOT NULL,
quantity INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products(id)
);
-- src/main/resources/data.sql
INSERT INTO products (name, price) VALUES ('Widget A', 9.99);
INSERT INTO products (name, price) VALUES ('Widget B', 19.99);
INSERT INTO products (name, price) VALUES ('Gadget Pro', 49.99);
# Enable script-based initialisation (required in Spring Boot 2.5+)
spring.sql.init.mode=always
# If using Hibernate AND SQL scripts, defer data source initialisation
spring.jpa.defer-datasource-initialization=true
Switching to Persistent Mode
Replace the in-memory URL with a file path to persist the H2 database between restarts.
# Persistent H2 — stores to a file
spring.datasource.url=jdbc:h2:file:./data/mydb;AUTO_SERVER=true
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# Use validate or update (not create-drop) for persistent mode
spring.jpa.hibernate.ddl-auto=update
The AUTO_SERVER=true
spring.datasource.*