Spring Boot H2 tutorial

In Spring Boot H2 tutorial, we show how to work with an embedded H2 in-memory database in Spring Boot. A simple REST application is created.

Spring is a Java application framework for developing Java enterprise applications. It also helps integrate various enterprise components. Spring Boot makes it easy to create Spring-powered, production-grade applications and services with minimum setup requirements.

Jetty is an open source project providing an HTTP server, an HTTP client, and a Java servlet container. The project is a part of t he Eclipse Foundation. Jetty is a mature project, which started in 1995. Jetty can be easily embedded in devices, tools, frameworks, application servers, and clusters.

H2 is an open source relational database management system created entirely in Java. It can be embedded in Java applications or run in the client-server mode. It is easy to deploy and install and has small footprint.

JdbcTemplate is a Spring library that helps programmers create applications that work with relational databases and JDBC. It takes care of many tedious and error-prone low-level details such as handling transactions, cleaning up resources, and correctly handling exceptions. JdbcTemplate is shipped in Spring's spring-jdbc module.

JSON (JavaScript Object Notation) is a lightweight data-interchange format. Humans can easily read and write and machines parse and generate JSON. The official Internet media type for JSON is application/json. The JSON filename extension is .json.

A RESTFul application follows the REST architectural style, which is used for designing networked applications. RESTful applications generate HTTP requests which perform CRUD (Create/Read/Update/Delete) operations on resources.

Spring Boot RESTFul application

H2 can be easily used with Spring Boot. When Spring Boot detects H2 in the POM file, it automatically configures an in-memory H2 database for the application.

The following is a simple Spring Boot application that has RESTFul services. The application runs with embedded Jetty server.

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │      └── zetcode
    │   │          ├── bean
    │   │          │  └── Car.java
    │   │          ├── main
    │   │          │  └── Application.java
    │   │          ├── service
    │   │          │  ├── CarService.java
    │   │          │  └── ICarService.java
    │   │          └── web
    │   │              └── MyController.java
    │   └── resources
    │       ├── application.yml
    │       ├── data-h2.sql
    │       └── schema-h2.sql
    └── test
        └── java

This is the project structure.

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.zetcode</groupId>
    <artifactId>SpringBootH2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>      
    
    <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>      
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>        
           
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>      
        
    </dependencies>    

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>            
        </plugins>
    </build>      
    
</project>

The Maven pom.xml file contains dependencies for Jetty, H2 driver, and Spring framework.

Car.java
package com.zetcode.bean;

public class Car {
    
    private Long id;
    private String name;
    private int price;
    
    public Car() {}

    public Car(Long id, String name, int price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    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 int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" + "id=" + id + ", name=" + name + ", price=" + price + '}';
    }
}

This is Car bean class. It contains item ID, name, and price.

application.yml
spring: 
    datasource:
        platform: h2

The application.yml is the main Spring Boot configuration file. The platform value is used in SQL initialization scripts: schema-${platform}.sql and data-${platform}.sql.

Notice that we do not configure the datasource. This is because Spring automatically configures H2 in the in-memory mode if there is no configuration data. We wanted to have an in-memory database, so we leave Spring to do the automatic configuration.

schema-h2.sql
CREATE TABLE Cars(ID BIGINT PRIMARY KEY AUTO_INCREMENT, 
                  NAME VARCHAR(100), PRICE INT);

This SQL script creates the Cars table.

data-h2.sql
INSERT INTO Cars(Name, Price) VALUES('Audi', 52642);
INSERT INTO Cars(Name, Price) VALUES('Mercedes', 57127);
INSERT INTO Cars(Name, Price) VALUES('Skoda', 9000);
INSERT INTO Cars(Name, Price) VALUES('Volvo', 29000);
INSERT INTO Cars(Name, Price) VALUES('Bentley', 350000);
INSERT INTO Cars(Name, Price) VALUES('Citroen', 21000);
INSERT INTO Cars(Name, Price) VALUES('Hummer', 41400);
INSERT INTO Cars(Name, Price) VALUES('Volkswagen', 21600);

This script fills the table with data. Both scripts are located in the root of the classpath.

MyController.java
package com.zetcode.web;

import com.zetcode.bean.Car;
import com.zetcode.service.ICarService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private ICarService carService;

    @RequestMapping("/")
    public String index(Model model) {
        
        return "Home page";
    }

    @RequestMapping(name = "/cars", method = RequestMethod.GET)
    public List<Car> cars() {

        List<Car> cars = carService.findAll();

        return cars;
    }
}

In the MyController, we have two methods that react to two requests. The traditional MVC controller uses a view technology to perform server-side rendering to HTML. The RESTful web service controller writes data to the HTTP response. The default format is JSON.

@RestController
public class MyController {

@RestController annotation creates RESTFul web services in Spring.

@Autowired
private ICarService carService;

We inject CarService object into the attribute. The service object is used to retrieve data from the database.

@RequestMapping("/")
public String index(Model model) {
    
    return "Home page";
}

For the root path, we return a string message.

@RequestMapping(name = "/cars", method = RequestMethod.GET)
public List<Car> cars() {

    List<Car> cars = carService.findAll();

    return cars;
}

In the cars() method, we find all cars with the findAll() method. The list of car objects is translated into JSON with a Spring message converter.

ICarService.java
package com.zetcode.service;

import com.zetcode.bean.Car;
import java.util.List;

public interface ICarService {

    public List<Car> findAll();
}

ICarService provides a contract method to get all cars from the data source.

CarService.java
package com.zetcode.service;

import com.zetcode.bean.Car;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class CarService implements ICarService {

    @Autowired
    private JdbcTemplate jtm;

    @Override
    public List<Car> findAll() {

        String sql = "SELECT * FROM Cars";

        List<Car> cars = jtm.query(sql, new BeanPropertyRowMapper(Car.class));

        return cars;
    }
}

CarService contains the implementation of the findAll() method. We retrieve all cars from the Cars table with the help of the JdbcTemplate.

@Autowired
private JdbcTemplate jtm;

JdbcTemplate is injected.

String sql = "SELECT * FROM Cars";

This is SQL to be executed. We select all cars from the Cars table.

List<Car> cars = jtm.query(sql, new BeanPropertyRowMapper(Car.class));

BeanPropertyRowMapper converts a row into a new instance of the specified mapped target class.

Application.java
package com.zetcode.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication(scanBasePackages = "com.zetcode")
public class Application {

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);
    }
}

The Application sets up the Spring Boot application.

$ mvn spring-boot:run

We start Spring Boot application.

$ curl localhost:8080
Home page

We get the string message when we request the home page.

$ curl localhost:8080/cars
[{"id":1,"name":"Audi","price":52642},{"id":2,"name":"Mercedes","price":57127},
{"id":3,"name":"Skoda","price":9000},{"id":4,"name":"Volvo","price":29000},
{"id":5,"name":"Bentley","price":350000},{"id":6,"name":"Citroen","price":21000},
{"id":7,"name":"Hummer","price":41400},{"id":8,"name":"Volkswagen","price":21600}]

Here we get the list of cars in a JSON string.

In this tutorial, we used an in-memory H2 database in a RESTFul web application. The application used Spring Boot framework and was run in a web environment with embedded Jetty. You might also be interested in these related tutorials: Spring Boot DataSourceBuilder tutorial, Spring Boot iText tutorial, Spring Boot RESTFul application, Introduction to Spring web applications, Spring Boot first web application, and Java tutorial.