eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (cat=Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

1. Introduction

The H2 database engine is a popular open-source database built on Java. In this brief tutorial, we’ll learn how to automatically create a schema for the H2 in-memory database.

2. What Is H2?

The H2 database engine is a Java-based database that is both SQL and JDBC (Java Database Connectivity) compliant. It has a number of features that set it apart from other relational databases:

  • Persistence: it can operate as a purely in-memory database or using a file system.
  • Mode: runs as a stand-alone server or embedded inside another application.

Both of these characteristics make H2 a great choice for development and testing purposes. However, because of its transient nature, it can also present some challenges.

When connecting to an H2 in-memory database, the schema may not exist. This is because in-memory databases are transient in nature and only survive as long as the application they are running inside is also running. Once that application is terminated, the entire contents of the in-memory database are lost.

Next, we’ll see a few different ways to initialize an H2 in-memory database when connecting to it.

3. Automatically Creating Schemas in H2

There are several approaches for automatically creating schemas for H2 in-memory databases. As with most things, there are pros and cons to each, and the choice of which one to use depends on multiple factors.

3.1. Plain Java

The example below shows how to initialize an in-memory H2 database with plain Java code and JDBC. This is a good option for applications that aren’t using Spring or other frameworks that provide database connectivity:

Connection conn = DriverManager.getConnection(
  "jdbc:h2:mem:baeldung;INIT=CREATE SCHEMA IF NOT EXISTS baeldung",
  "admin",
  "password");

In the above example, we use the connection URL to specify the schema to create. We can also pass additional commands to further initialize the database:

Connection conn = DriverManager.getConnection(
  "jdbc:h2:mem:baeldung;INIT=CREATE SCHEMA IF NOT EXISTS baeldung\\;SET SCHEMA baeldung;CREATE TABLE users (name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL);",
  "admin",
  "password");

Because all of these commands can make the URL difficult to read, H2 also supports initializing an in-memory database by referencing an SQL file. First, we create the file with the initialization statements:

CREATE SCHEMA IF NOT EXISTS baeldung;
SET SCHEMA baeldung;
CREATE TABLE users (name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL);

Then we use a slightly modified connection URL to reference the file:

Connection conn = DriverManager.getConnection(
  "jdbc:h2:mem:baeldung;INIT=RUNSCRIPT FROM 'h2init.sql';",
  "admin",
  "password");

3.2. Spring Boot

When working with Spring Boot applications, we can also utilize familiar Spring data properties to initialize H2 in-memory databases.

First, we can provide all of the initialization statements in the URL itself, just like above. We start by defining the Spring properties for the H2 data source:

spring.datasource.url=jdbc:h2:mem:baeldung;INIT=CREATE SCHEMA IF NOT EXISTS baeldung\\;SET SCHEMA baeldung;

Then we can use the default Datasource bean as we do in any normal application:

public void initDatabaseUsingSpring(@Autowired DataSource ds) {
    try (Connection conn = ds.getConnection()) {
        conn.createStatement().execute("create table users (name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL);");
        conn.createStatement().execute("insert into users (name, email) values ('Mike', '[email protected]')");
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

Just like with plain Java code, we can also reference a SQL file in the connection URL that contains all of the initialization statements. All we have to do is update our properties:

spring.datasource.url=jdbc:h2:mem:baeldung;INIT=RUNSCRIPT FROM 'src/main/resources/h2init.sql';

Notably, H2 doesn’t load resources through Spring Boot. Therefore, we have to reference the file path in its full context of where the application is running.

And now we can use the Datasource like before, but without having to initialize the schema first:

private void initDatabaseUsingSpring(@Autowired DataSource ds) {
    try (Connection conn = ds.getConnection()) {
        conn.createStatement().execute("insert into users (name, email) values ('Mike', '[email protected]')");
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

Finally, when using Spring Boot, we can also leverage the SQL init mode without relying on H2 features. We simply rename our initialization file to data.sql and change our properties slightly:

spring.datasource.url=jdbc:h2:mem:baeldung
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=admin
spring.datasource.password=password
spring.sql.init.mode=embedded

We should note that our properties make no mention of a schema or initialization file.

3.3. Spring XML

Additionally, if we are using plain Spring XML to configure a Datasource, we can include the initialization statements there as well.

Let’s see how to create the schema:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.h2.Driver"/>
    <property name="url" value="jdbc:h2:mem:testdb;INIT=CREATE SCHEMA IF NOT EXISTS baeldung\\;SET SCHEMA baeldung;"/>
    <property name="username" value="admin"/>
    <property name="password" value="password"/>
</bean>

As we saw before, having multiple initialization statements in the URL can make it difficult to read the properties. Therefore, it’s a good idea to put them into a single SQL file and reference that in the URL:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.h2.Driver"/>
    <property name="url" value="jdbc:h2:mem:testdb;INIT=RUNSCRIPT FROM 'src/main/resources/h2init.sql';"/>
    <property name="username" value="admin"/>
    <property name="password" value="password"/>
</bean>

4. Connect to a Specific Schema in H2 Database

At the outset, a database refers to a collection of data and meta-data, whereas a schema is a collection of objects (tables, indexes, etc.) stored in a database. When we connect to an H2 database instance, we connect to a database. However, we can set the current schema to a specific schema on connection.

Furthermore, the H2 database management system supports two types of databases: disk-based and in-memory. Accordingly, a disk-based H2 database stores the data in the filesystem on a disk. Further,  an in-memory H2 database stores the data in memory. Therefore, an in-memory database is transient, and thus data is never persisted on disk.

When we don’t specify a schema, H2 sets it to the default schema, which is PUBLIC. Let’s discuss connecting to the database and setting a non-default schema.

4.1. Using the H2 Shell

Let’s launch the H2 shell with the java org.h2.tools.Shell command. Thereafter, we are prompted to specify a URL. We specify a file-based URL when we want to use a disk-based H2 database (for example, TEST_DB):

jdbc:h2:~/TEST_DB

On providing a value for each of the prompts; Driver, User (e.g. sa), and Password (e.g. empty option), we are connected to the H2 shell as indicated by a sql> prompt. H2 creates the TEST_DB, if it doesn’t already exist, on the disk as a file called TEST_DB.mv.

Thereupon, let’s find the current schema:

sql>SELECT CURRENT_SCHEMA;
CURRENT_SCHEMA
PUBLIC

The current schema is the default, PUBLIC.

We can connect to a specific schema by including the schema name to set in the connection URL itself. However, let’s first create an example schema TEST_SCHEMA while connected to the H2 shell:

sql>CREATE SCHEMA TEST_SCHEMA AUTHORIZATION SA;

Thereafter, let’s verify it created the new schema:

sql>SHOW SCHEMAS;
SCHEMA_NAME
TEST_SCHEMA
INFORMATION_SCHEMA
PUBLIC

Let’s quit the H2 shell with the quit command. Let’s now connect to the TEST_DB again. Furthermore, this time we set the schema to TEST_SCHEMA in the connection URL, when prompted, using the INIT property:

jdbc:h2:~/TEST_DB;INIT=SET SCHEMA TEST_SCHEMA

On connecting to the H2 shell, let’s find the current schema:

sql>SELECT CURRENT_SCHEMA;
CURRENT_SCHEMA
TEST_SCHEMA

Indeed, it’s the TEST_SCHEMA we want to connect to.

Furthermore, we can create the schema that we want to connect to, or more precisely, set to, in the connection URL itself. Let’s create a new H2 database called TEST_DB_2 and in it create a new schema called FIRST_SCHEMA. Accordingly, we should use the directory path to the database on Windows by including \\ between directory names. Furthermore, we should escape the delimiter ; between multiple SQL commands in the INIT using a single \ in the connection URL:

jdbc:h2:C:\\Users\\user1\\TEST_DB_2;INIT=CREATE SCHEMA IF NOT EXISTS FIRST_SCHEMA\;SET SCHEMA FIRST_SCHEMA

On connecting, let’s verify the current schema:

sql>SELECT CURRENT_SCHEMA;
CURRENT_SCHEMA
FIRST_SCHEMA

Indeed, it’s the FIRST_SCHEMA we created and set in the connection URL.

Likewise, we can specify a URL for an in-memory H2 database when we want to connect to a specific database schema. To demonstrate, let’s create an in-memory database called test_db and a schema called TEST_SCHEMA. Furthermore, we create and set the schema in the connection URL itself:

jdbc:h2:mem:test_db;INIT=CREATE SCHEMA TEST_SCHEMA\;SET SCHEMA TEST_SCHEMA

On connecting, let’s verify the schema connected to:

sql>SELECT CURRENT_SCHEMA;
CURRENT_SCHEMA
TEST_SCHEMA

Indeed, it’s the TEST_SCHEMA we created and set in the connection URL.

4.2. Using a JDBC Application

We can use the JDBC API and H2’s JDBC driver to connect to an H2 database. Furthermore, we can connect to a specific schema. We have the option to connect to an existing database and schema or create a new database and schema. Accordingly, we specify the database and schema to connect to in the database connection URL itself. Let’s create a new database called TEST_DB and, in it, a new schema called TEST_SCHEMA. Additionally, we set the schema to connect to. We use the INIT property in the connection URL when we want to run SQL statement/s on connecting to a database.

Let’s use a JUnit 5 test to verify that we connect to the schema we want to connect to:

@Test
public static void whenConnectingToSpecificSchema_ShouldReturnTheSpecificSchema() throws Exception {
    Connection conn = DriverManager.getConnection(
      "jdbc:h2:~/TEST_DB;INIT=CREATE SCHEMA IF NOT EXISTS TEST_SCHEMA\\;SET SCHEMA TEST_SCHEMA",
      "sa",
      "");
      
    Statement stmt=conn.createStatement();
      
    ResultSet rs=stmt.executeQuery("SELECT CURRENT_SCHEMA");
    rs.first();
      
    String actualSchema = rs.getString(1);
    String expectedSchema = new String("TEST_SCHEMA");

    Assertions.assertTrue(actualSchema.equals(expectedSchema));
}

The JUnit test should pass when have indeed connected to the schema we need to connect to, TEST_SCHEMA in the example. Similarly, we can connect to an in-memory H2 database.

5. Conclusion

The H2 in-memory database is one of the more popular in-memory and embedded database options for Java developers. Because it’s fast and has a small footprint, it is great for use cases like software tests and automated pipelines.

In this article, we saw several ways to ensure that our H2 in-memory database is automatically initialized and ready to use for querying when our application starts. Whether we use plain JDBC or Spring framework, it only takes a few lines of configuration to ensure our in-memory database is fully initialized and ready to use on startup.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – Summer Sale 2026 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

Course – Summer Sale 2026 – NPI (All)
announcement - icon

Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:

>> EXPLORE ACCESS NOW

eBook Jackson – NPI EA – 3 (cat = Jackson)