Spring Boot Web MVC Using Embedded H2 Database Example

In this example, we will show you how to develop a spring boot web application using spring web MVC, spring data JPA, spring thymeleaf template engine, and h2 embedded database library jars. This web application provides two functions, one function can add employees and the other function can list added employees. Please see the function demo in the below video.

If you can not watch the above video, you can see it on the youtube URL https://youtu.be/CXeykzM9jtI

1. Create Spring Boot Web Application.

  1. First, we should create a spring boot web application using the spring tool suite New Spring Starter Project wizard. You can refer article Spring Boot Hello World Example In STS.
  2. The spring boot web application Name value is SpringBootWebMVC, the Package value is com.dev2qa.example.mvc.
  3. Select JPA, H2, Thymeleaf, and Web dependencies library in the following New Spring Starter Project Dependencies wizard panel.
  4. You can use the spring data JPA library to operate embedded h2 database table data flexible, the h2 JDBC driver classes are provided in the h2 library.
  5. The Thymeleaf library provides a template engine that is used to render Html web pages. And the spring web library is used to construct the application web MVC structure.
  6. Click the Finish button to complete the spring boot starter project creation process.

2. Spring Boot Web Application Project Files Structure.

  1. Below is the example project panel, it contains below source files.
    C:\WORKSPACE\WORK\DEV2QA.COM-EXAMPLE-CODE\SPRINGBOOT\SPRINGBOOTWEBMVC
    │   .gitignore
    │   mvnw
    │   mvnw.cmd
    │   pom.xml
    │
    ├───.mvn
    │   └───wrapper
    │           maven-wrapper.jar
    │           maven-wrapper.properties
    │
    └───src
        ├───main
        │   ├───java
        │   │   └───com
        │   │       └───dev2qa
        │   │           └───example
        │   │               │   SpringBootWebMvcApplication.java
        │   │               │
        │   │               ├───constant
        │   │               │       ConstantVariable.java
        │   │               │
        │   │               ├───controller
        │   │               │       CustomErrorController.java
        │   │               │       EmployeeController.java
        │   │               │
        │   │               ├───model
        │   │               │       Employee.java
        │   │               │
        │   │               └───repository
        │   │                       EmployeeRepository.java
        │   │
        │   └───resources
        │       │   application.properties
        │       │
        │       └───templates
        │               addEmployee.html
        │               error-500.html
        │               error.html
        │               listEmployee.html
        │
        └───test
            └───java
                └───com
                    └───dev2qa
                        └───example
                            └───mvc
                                    SpringBootWebMvcApplicationTests.java
  2. SpringBootWebMvcApplication.java: Spring boot application main class.
  3. ConstantVariable.java: Save the constant variables used in this example.
  4. CustomErrorController.java: This class is used to define a custom error page to display to client users when there are errors occurred. Please refer to the How To Disable Or Customize Spring Boot Whitelabel Error Page.
  5. EmployeeController.java: This is the main controller in this example, it provides three function mapping to different request url, the three functions provide display add employee form page, add employee, and list employees feature.
  6. Employee.java: This is the entity java bean that presents one employee information, it maps to the h2 database EMPLOYEE table.
  7. EmployeeRepository.java: This is an interface that extends org.springframework.data.jpa.repository.JpaRepository, the JpaRepository interface has encapsulated all basic DB operations ( insert, update, select and delete ) for you, you can use it directly to operate table data without coding SQL commands.
  8. addEmployee.html: Display the add employee form page, user can input employee info on this page and click submit button to add one employee.
  9. listEmployee.html: List added employees info in a table.
  10. application.properties: This is the example configuration file, contains h2 database-related data source JDBC connection information.
  11. pom.xml: The maven dependencies definition XML file. Define example used libraries.

3. Spring Boot Web MVC Example Source Files.

3.1 SpringBootWebMvcApplication.java

package com.dev2qa.example;

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

/* @SpringBootApplication consists of @Configuration, @ComponentScan and @EnableAutoConfiguration.
 * This annotation enable component scan and auto configuration. */

@SpringBootApplication

/*
@Configuration
@ComponentScan(basePackages = {"com.dev2qa.example"})
@EnableAutoConfiguration
*/
public class SpringBootWebMvcApplication {

    public static void main(String[] args) {
      /* Responsible for launching the boot application. */
        SpringApplication.run(SpringBootWebMvcApplication.class, args);
    }
}

3.2 ConstantVariable.java

package com.dev2qa.example.constant;

public class ConstantVariable {

    public static String EMPLOYEE_LIST = "employees";

}

3.3 CustomErrorController.java

You can find the source code of this java file in the article How To Disable Or Customize Spring Boot Whitelabel Error Page.

3.4 EmployeeController.java

package com.dev2qa.example.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.dev2qa.example.constant.ConstantVariable;
import com.dev2qa.example.model.Employee;
import com.dev2qa.example.repository.EmployeeRepository;

@Controller
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeRepository employeeRepository;

    /* List added employees. */
    @RequestMapping(value="/listEmployee", method=RequestMethod.GET)
    public String listEmployeeList(Model model) {
        List<Employee> employeeList = this.employeeRepository.findAll();

        model.addAttribute(ConstantVariable.EMPLOYEE_LIST, employeeList);

        return "listEmployee";
    }

    /* Display add employee form page. */
    @RequestMapping(value="/addEmployeePage", method=RequestMethod.GET)
    public String addEmployeePage() {
        return "addEmployee";
    }

    /* Add user submitted employee info to h2 databae and redirect to list employees page. */
    @RequestMapping(value="/addEmployee", method=RequestMethod.POST)
    public String addEmployee(Employee employee) {
        employeeRepository.save(employee);
        return "redirect:/employee/listEmployee";
    }
}

3.5 Employee.java

package com.dev2qa.example.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/* Annotate Employee class as JPA Entity class. 
 * Because do not specify the entity table name 
 * then use EMPLOYEE as the table name by default. */
@Entity
public class Employee {

    /* Identify id as this entity's unique identifier. The id value is auto generated. */
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String userName;

    private String password;

    private String email;

    private String sex;

    private long age;

    private String title;

    private long salary;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public long getAge() {
        return age;
    }

    public void setAge(long age) {
        this.age = age;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public long getSalary() {
        return salary;
    }

    public void setSalary(long salary) {
        this.salary = salary;
    }
}

3.6 EmployeeRepository.java

package com.dev2qa.example.repository;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.dev2qa.example.model.Employee;

/* Extends JpaRepository which has provide all basic crud methods to operate Employee table. */
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    /* We add a custom method here but do not use it in this example. 
     * The method name must follow findBy<column name> pattern, then JpaRepository
     * will implement the detailed JDBC query code which we do not need to care about, we just 
     * need to call this method and pass in the userName to get the result list. 
     * */
    List<Employee> findByUserName(String userName);
}

3.7 addEmployee.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Add Employee</title>
    </head>
    <body>
        <h2>Add Employee </h2>
        <br/>
        <br/>
        <br/>

        <form method="post" action="/employee/addEmployee">
            <table border=0 >
            <tr><td align="right">User Name:</td><td align="left"><input type="text" name="userName" size="50"></input></td></tr>
            <tr><td align="right">Password:</td><td align="left"><input type="password" name="password" size="50"></input></td></tr>
            <tr><td align="right">Email:</td><td align="left"><input type="text" name="email" size="50"></input></td></tr>
            <tr><td align="right">Title:</td><td align="left"><input type="text" name="title" size="50"></input></td></tr>
            <tr><td align="right">Sex:</td><td align="left"><input type="radio" name="sex" value="male"> Male<input type="radio" name="sex" value="female"> Female</td></tr>
            <tr><td align="right">Salary:</td><td align="left"><input type="text" name="salary" size="50"></input></td></tr>
            <tr><td align="right">Age:</td><td align="left"><input type="text" name="age" size="50"></input></td></tr>
            <tr><td align="right"></td><td align="left"><input type="submit"></input></td></tr>
        </table>
    </form>

</body>
</html>

3.8 listEmployee.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>List Employee</title>
    </head>
    <body>
        <h2>Employee List</h2>

        <a th:href="@{'/employee/addEmployeePage'}">Add Employee</a>

        <br/>

        <table th:if="${ not #lists.isEmpty(employees) }" border=1>
        <tr>
            <td>User Name</td>
            <td>Password</td>
            <td>Email</td>
            <td>Title</td>
            <td>Sex</td>
            <td>Salary</td>
            <td>Age</td>
        </tr>
        <tr th:each="employee : ${employees}">
            <td th:text="${employee.userName}"></td>
            <td th:text="${employee.password}"></td>
            <td th:text="${employee.email}"></td>
            <td th:text="${employee.title}"></td>
            <td th:text="${employee.sex}"></td>
            <td th:text="${employee.salary}"></td>
            <td th:text="${employee.age}"></td>
        </tr>
    </table>

</body>
</html>

3.9 application.properties

#server.error.whitelabel.enabled=false
#spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

# Enable h2 database console.
spring.h2.console.enabled=true

# Define h2 database jdbc connection parameter values.
# When example start, you can access the embedded h2 database with below parameter values to see the EMPLOYEE table.
spring.datasource.url=jdbc:h2:~/employee_db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

3.10 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.dev2qa</groupId>
    <artifactId>SpringBootWebMVC</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringBootWebMVC</name>
    <description>Spring Boot Web MVC Example.</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.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-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>

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

3.11 How To Connect To The Embedded H2 Database & Browse The Database Table.

  1. When you run the above example application, you can access the h2 DB console in a web browser with url http://localhost:8080/h2-console/. It will show the h2 database Login page.
  2. Then you should input the below h2 database JDBC parameter values on the Login page.

    Saved Settings:  Generic H2 (Embedded)
    Setting Name: Generic H2 (Embedded)
    
    Driver Class: org.h2.Driver
    JDBC URL: jdbc:h2:~/employee_db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    User Name: sa
    Password:
  3. After you input the correct h2 database information, when you click the Connect button, it will connect to the h2 database server and show the EMPLOYEE table on the web page left panel, click the table will list all the table data on the page right side.

Reference

  1. H2 Database Tutorial
  2. Spring Boot Resolve Whitelabel Error Page Example

Leave a Comment

Your email address will not be published. Required fields are marked *

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