In this tutorial we will learn how to create a basic Spring Boot application that uses H2 Database. We will provide at first an overview of how to use H2 DB with Spring Boot, then we will use the Spring Boot CLI to bootstrap an example CRUD application.
Overview of H2 Database
Firstly, H2 Database is a pure Java Database with JDBC and Transactional support. You can run it in two modes:
- Embedded within a Java Process (for example a Spring Boot application)
- As standalone application
You can also use either in-memory (volatile) storage or disk-based storage.
Spring Boot can auto-configure an embedded H2 with the following settings:
Driver Class | org.h2.Driver |
JDBC URL | jdbc:h2:mem:testdb |
User Name | sa |
Password | <blank> |
The only requirement is to include the following dependency and the embedded H2 Database will start:
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency>
If you want to customize the Database settings, you can add them within your application.properties:
spring.datasource.url=jdbc:h2:mem:demodb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=secret spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
Let’s see how to build a complete Spring Boot CRUD application using H2 Database
Creating a CRUD Spring Boot application with H2 Database
We will start from Spring Command Line Interface. You can however surf to the Spring Initializr Web application if you prefer.
Our Web application, named spring-crud-h2, will require the following dependencies as specified by spring init:
$ spring init -dweb,data-jpa,h2,validation,thymeleaf spring-crud-h2
Important: Until Spring Boot version 2.2 the starter spring-boot-starter-web had as dependency the starter spring-boot-starter-validation. In Spring Boot 2.3 the starter spring-boot-starter-validation is NOT a dependency of the starter spring-boot-starter-web anymore so you need to add it explicitly.
What is Thymeleaf? In a nutshell, Thymeleaf is an XML/XHTML/HTML5 template engine written in Java which is able to apply a set of transformations to template files in order to display data and/or text produced by your applications.
The following dependencies will be added to your pom.xml file:
<?xml version="1.0" encoding="UTF-8"?> <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-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </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>
Right now we have just a DemoApplication to bootstrap the project:
package com.example.cruddemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
Next, we will add our Entity object Customer.java:
package com.example.cruddemo.entities; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.validation.constraints.NotBlank; @Entity public class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @NotBlank(message = "Name is required") private String name; @NotBlank(message = "Surname is required") private String surname; @NotBlank(message = "Email is required") private String email; public Customer() {} public Customer(String name, String email) { this.name = name; this.email = email; } public void setId(long id) { this.id = id; } public long getId() { return id; } public void setName(String name) { this.name = name; } public void setEmail(String email) { this.email = email; } public String getName() { return name; } public String getEmail() { return email; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } }
As you can see, our Entity class is pretty simple and contains some Validation constraints to ensure you don’t enter blank data in the fields. Next, let’s add the core part of it, the CustomerController:
package com.example.cruddemo.controllers; import javax.validation.Valid; import com.example.cruddemo.entities.Customer; import com.example.cruddemo.repositories.CustomerRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @Controller public class CustomerController { private final CustomerRepository customerRepository; @Autowired public CustomerController(CustomerRepository customerRepository) { this.customerRepository = customerRepository; } @GetMapping("/new") public String showSignUpForm(Customer customer) { return "add-customer"; } @GetMapping("/edit/{id}") public String showUpdateForm(@PathVariable("id") long id, Model model) { Customer customer = customerRepository .findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid customer Id:" + id)); model.addAttribute("customer", customer); return "update-customer"; } @GetMapping("/delete/{id}") public String deleteUser(@PathVariable("id") long id, Model model) { Customer customer = customerRepository .findById(id) .orElseThrow(() -> new IllegalArgumentException("Invalid customer Id:" + id)); customerRepository.delete(customer); model.addAttribute("customers", customerRepository.findAll()); return "index"; } @PostMapping("/addcustomer") public String addUser(@Valid Customer customer, BindingResult result, Model model) { if (result.hasErrors()) { return "add-customer"; } customerRepository.save(customer); model.addAttribute("customers", customerRepository.findAll()); return "index"; } @PostMapping("/update/{id}") public String updateUser( @PathVariable("id") long id, @Valid Customer customer, BindingResult result, Model model) { if (result.hasErrors()) { customer.setId(id); return "update-customer"; } customerRepository.save(customer); model.addAttribute("customers", customerRepository.findAll()); return "index"; } }
As you can see, this Controller class manages all aspects of the Entity through REST mappings. Finally, we will add a Repository class to include a method to findByName the Customers:
package com.example.cruddemo.repositories; import com.example.cruddemo.entities.Customer; import java.util.List; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @Repository public interface CustomerRepository extends CrudRepository<Customer, Long> { List<Customer> findByName(String name); }
Building the Spring Boot view
We will now add the HTML pages using the Thymeleaf engine. First off, the index.html page which list the existing Customers:
<body> <div th:switch="${customers}"> <div class="row"> <div> <h2 th:case="null">No Customers.</h2> <div th:case="*"> <h2>Customers</h2> <table border="1"> <thead> <tr> <th>Name</th> <th>Surname</th> <th>Email</th> <th>Edit</th> <th>Delete</th> </tr> </thead> <tbody> <tr th:each="customer : ${customers}"> <td th:text="${customer.name}"></td> <td th:text="${customer.surname}"></td> <td th:text="${customer.email}"></td> <td> <a th:href="@{/edit/{id}(id=${customer.id})}">EDIT</a> </td> <td> <a th:href="@{/delete/{id}(id=${customer.id})}">DELETE</a> </td> </tr> </tbody> </table> </div> <p> <a href="/new">Add Customer</a> </p> </div> </div> </div> </body>
And now two pages, the add-customer.html page to insert a new Customer:
<body> <div> <h2>New Customer</h2> <div> <div> <form action="#" th:action="@{/addcustomer}" th:object="${customer}" method="post"> <div class="row"> <div > <label for="name">Name</label> <input type="text" th:field="*{name}" id="name" placeholder="Name"> <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" ></span> </div> <div > <label for="surname">Surname</label> <input type="text" th:field="*{surname}" id="surname" placeholder="Surname"> <span th:if="${#fields.hasErrors('surname')}" th:errors="*{surname}" ></span> </div> <div > <label for="email">Email</label> <input type="text" th:field="*{email}" id="email" placeholder="Email"> <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}" ></span> </div> </div> <div class="row"> <div > <input type="submit" value="Add Customer"> </div> </div> </form> </div> </div> </div> </body>
And the update-customer.html to Edit an existing customer:
<body> <div> <h2>Update Customer</h2> <div class="row"> <div> <form action="#" th:action="@{/update/{id}(id=${customer.id})}" th:object="${customer}" method="post"> <div class="row"> <div> <label for="name" >Name</label> <input type="text" th:field="*{name}" id="name" placeholder="Name"> <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" ></span> </div> <div> <label for="surname" >Surname</label> <input type="text" th:field="*{surname}" id="surname" placeholder="Name"> <span th:if="${#fields.hasErrors('surname')}" th:errors="*{surname}" ></span> </div> <div> <label for="email" >Email</label> <input type="text" th:field="*{email}" id="email" placeholder="Email"> <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}" ></span> </div> </div> <div class="row"> <div class="col-md-6 mt-5"> <input type="submit" class="btn btn-primary" value="Update Customer"> </div> </div> </form> </div> </div> </div> </body>
Compile your application then you can run it as usual with java -jar or with:
$ mvn spring-boot:run
And here’s our application in action (graphic really essential!)
Home Page:
Add a new Customer:
Customer list with Edit/Delete:
Connecting to the H2 Database Web Console
H2 DB includes a Web application to manage/view your Db structure. To enable the H2 Database Web application you need to add the following property in your application.properties:
spring.h2.console.enabled=true
Now you can connect to the console which is available at: http://localhost:8080/h2-console/
Click Connect to enter in the selected DB Schema.
Source code
You can find the source code for this article here: https://github.com/fmarchioni/masterspringboot/tree/master/crud/spring-crud-h2/cruddemo
You can check the following tutorial to learn how to use PostgreSQL as database: How to create a Spring Boot Crud JPA application with PostgreSQL
Found the article helpful? if so please follow us on Socials