Enterprise Java

Understanding H2 InMemory Database with Spring Boot

Introduction

Basically the database setup involves several steps before we can use it through configured datasource in our application. This actually is required in case of actual project implementations. However, there are situations where we just need a POC to be done for something, and the whole database setup thing still becomes an obligation. Similarly, for unit tests, it would be ideal to have our own set of records in the database, so its independent, without getting impacted by the data changes in the deployed environment. For such use cases, in-memory databases are the ideal solution.

An in-memory database gets created when the application starts, while it gets destroyed when the application stops.

Spring Boot integrates H2 database with lot of ease. So you can easily and quickly switch between a real database and an in-memory database.

Note that, H2 InMemory Database is a relational DBMS written in Java.

Let’s check out a quick demo.

Implementation

Lets generate the Spring Boot project from Spring initializr. Ensure you add Web, JPA, H2 and DevTools dependencies as shown below.

H2 InMemory Database

Let’s look at the generated pom file.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
 
	<groupId>com.jcombat</groupId>
	<artifactId>h2demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
 
	<name>h2demo</name>
	<description>Demo project for Spring Boot</description>
 
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.0.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
 
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>
 
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
 
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
 
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
 
</project>

We also notice application.properties file generated as –

application.properties

# H2
spring.h2.console.enabled=true
spring.h2.console.path=/h2
 
# Datasource
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver

The property spring.h2.console.enabled=true enables the web console at http://localhost:8080/h2

H2 InMemory Database

Click on Connect and you get into the page where you see available tables in the DB.

H2 InMemory Database

You might be wondering, how come Student table got created. The magic happens with data.sql placed at src/main/resources. Just ensure you have the insert statements in the data.sql file as mentioned below –

data.sql

insert into STUDENT
values(10001,'Ajay', 'AAA1');
 
insert into STUDENT
values(10002,'Ajit', 'AAA2');

Spring Boot Auto Configuration checks the values in the data.sql file and does the needful for you, i.e. creates the STUDENT table, and executes the insert statements. Smart!

Lets check out how we can operate on these student records.

To do that, let’s have the Student entity class created now.

Student.java

package com.jcombat.entity;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
 
@Entity
public class Student {
 
	@Id
	@GeneratedValue
	private Long id;
	private String name;
	private String section;
 
	public Student() {
	}
 
	public Student(Long id, String name, String section) {
		this.id = id;
		this.name = name;
		this.section = section;
	}
 
	public Long getId() {
		return id;
	}
 
	public void setId(Long id) {
		this.id = id;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public String getSection() {
		return section;
	}
 
	public void setSection(String section) {
		this.section = section;
	}
 
}

To access the database, let’s write a simple JPA interface which provides the required helper functions to do basic DB operations.

StudentRepository.java

package com.jcombat.repository;
 
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
 
import com.jcombat.entity.Student;
 
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
 
}

Let’s now customize the Spring Boot entry point class using Command Line Runner, so we will be able to execute our Spring Boot application from command line.

package com.jcombat.h2demo;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 
import com.jcombat.repository.StudentRepository;
 
@SpringBootApplication
@EntityScan("com.jcombat.entity")
@EnableJpaRepositories("com.jcombat.repository")
public class H2demoApplication implements CommandLineRunner {
 
	// mvn spring-boot:run
	private Logger LOG = LoggerFactory.getLogger("H2demoApplication");
	
	StudentRepository studentRepository;
	
	@Autowired
	public H2demoApplication(StudentRepository studentRepository) {
		this.studentRepository = studentRepository;
	}
 
	public static void main(String[] args) {
		SpringApplication.run(H2demoApplication.class, args);
	}
 
	@Override
	public void run(String... args) throws Exception {
		LOG.info("Student count in DB: {}", studentRepository.count());
	}
}

Executing the application

To run the application, you can either do it directly from your Eclipse IDE, or from command-line through below command –

mvn spring-boot:run

When executed, we see the below output displayed on console –

Download the source code

H2 InMemory Database

Published on Java Code Geeks with permission by Abhimanyu Prasad, partner at our JCG program. See the original article here: Understanding H2 InMemory Database with Spring Boot

Opinions expressed by Java Code Geeks contributors are their own.

Abhimanyu Prasad

Abhimanyu is a passionate tech blogger and senior programmer, who has an extensive end-to-end development experience with wide range of technologies. He is the founder and administrator at jCombat.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Valentino Pezzano
Valentino Pezzano
5 years ago

Hi Abhimanyu. Just a couple of friendly remarks. It’s about some annotations that actually are not required in this specific example.
1) The annotation @Autowired on the constructor of H2DemoApplication is not required. You are using constructor injection, which works fine without any explicit autowiring annotation.
2) The annotations EntityScan and EnableJpaRepositories in H2DemoApplication are also not required. These annotations are necessary only when your entities or your repositories are not in the application package or a subpackage of the application package (so if they are not in the package com.jcombat.h2demo or a subpackage of it).
Thanks for the example!

Back to top button