X

Hi, thank you for visiting here. Have a nice day. 👋

S

Building an application with Spring Boot, Thymeleaf, and MySQL.

This is a spring boot tutorial. We are going to build a simple Employee Management System web application.
Satoru Akiyama
ProgramingEnglish
Building an application with Spring Boot,  Thymeleaf,  and MySQL. photo
BlogAugust 20, 2021

Goal🤩

In this tutorial, you'll learn how to create a simple web application with Spring Boot. This is very useful for beginners to learn Spring Boot.

I will also provide my code.

Requirements🙏

  • Basic knowledge about Java and HTML.
  • You already have a local environment for Java development.

Tools and technologies we use 🔷

1. Java 11

We use Java 11.

2. Spring Boot

Spring Boot is an open source Java-based framework.

3. MySQL

We use MySQL as a database service. If you haven't downloaded it yet, please download it.

4. Thymeleaf

Thymeleaf is a modern server-side Java template engine for both web and standalone environments.

5. Eclipse

We use an Eclipse IDE. You can use your favorite one.

Let's get started!💫

Step1 Starting with Spring Initializr

Spring Initializr pulls in all the dependencies you need for your application and does most of the setup for you. Please visit the Spring Initializr and generate a new project as follows. (If your IDE has the Spring Initializr integration, you can complete this process from your IDE.)

Project: Maven Project

Language: Java

Spring Boot: 2.52

Project Metadata
  Group: com.example
  Artifact: employee-management-system
  Name: employee-management-system
  Description: Demo project for Spring Boot Web App
  Package name: com.example.employee-management-system
  Packaging: Jar
  Java: 11

Dependencies: Spring Web, Spring Data JPA, Thymeleaf, Spring Boot DevTools, MySQL Driver

Then, import the project which you generate in Spring Initializr into Eclipse workspace. If you don't know how to do that, refer to this article.

Step2 application.properties file

Spring Boot gives you H2 as the default database. When you want to use any other database (we use MySQL.), you need to define the attributes in the application.properties file.

Please open the src/main/resources/application.properties file and enter the attributes with the following code.

# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=your database url
spring.datasource.username=your database username
spring.datasource.password=your database password

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

Generally, the attribute of spring.datasource.url looks like this: jdbc:mysql://localhost:3306/employee-management-system

About spring.jpa.hibernate.ddl-auto see the Hibernate documentation for details.

Step3 Create packages

Next, create controller package, domain package, repository package and service package at src/main/java/com/example/com.example.employee-management-system. We're gonna make files under these packages later.

Step4 Create the @Entity Model

Create the Class called Employee at the domain package with the following code.

*Comments in the code might be helpful for you to understand what's going on in Spring Boot application

package com.example.employeemanagementsystem.domain;

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

@Entity // This tells Hibernate to create a table of this class
public class Employee {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	//	By @GeneratedValue, JPA makes a unique key automatically and applies the key to the field having @Id
	private long id;
	private String firstName;
	private String lastName;
	private String email;

	public Employee() {
	}

	public long getId() {
		return id;
	}

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

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

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

}

Step5 Create the Repository

Create the Class called EmployeeRepository at the repository package with the following code.

*Comments in the code might be helpful for you to understand what's going on in Spring Boot application

package com.example.employeemanagementsystem.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.satoruakiyama.employeemanagementsystem.domain.Employee;

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
	// This will be AUTO IMPLEMENTED by Spring into a Bean
}

JpaRepository is a JPA specific extension of Repository. It is useful for basic CRUD operations and also API for pagination and sorting. You can see details here.

Step6 Create the Service

Create the Class called EmployeeService at the service package with the following code.

*Comments in the code might be helpful for you to understand what's going on in Spring Boot application

package com.example.employeemanagementsystem.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.satoruakiyama.employeemanagementsystem.domain.Employee;
import com.satoruakiyama.employeemanagementsystem.repository.EmployeeRepository;

@Service // This means that this class is a service
public class EmployeeService {
	@Autowired
	// to get the bean which is auto-generated by Spring
	//	We will use it to handle the data
	EmployeeRepository employeeRepository;

	//	get all employees
	public List<Employee> getAllEmployees() {

		//		find all employees data, then return it
		return employeeRepository.findAll();
	}

	// save an employee
	public void saveEmployee(Employee emp) {
		//		save employee data to database
		employeeRepository.save(emp);
	}

	//	get employee by id
	public Employee getEmployeeById(Long id) {
		//		find an employee by id
		Employee emp = employeeRepository.getById(id);

		//		if there is not an employee who has the id, throw the error.
		if (emp == null) {
			throw new RuntimeException("Employee not found");
		}
		return emp;
	}

	//	delete employee by id
	public String deleteEmployeeById(Long id) {
		//		find an employee by id
		Employee emp = employeeRepository.getById(id);

		//		if there is not an employee who has the id, throw the error.
		if (emp == null) {
			throw new RuntimeException("Employee not found");
		}

		//		delete an employee who has the id from the database 
		employeeRepository.deleteById(id);
		return "Deleted: " + emp.getFirstName() + " " + emp.getLastName();
	}
}

Step7 Create the Controller

Create the Class called EmployeeController at the controller package with the following code.

*Comments in the code might be helpful for you to understand what's going on in Spring Boot application

package com.example.employeemanagementsystem.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import com.satoruakiyama.employeemanagementsystem.domain.Employee;
import com.satoruakiyama.employeemanagementsystem.service.EmployeeService;

@Controller // This means that this class is a Controller
public class EmployeeController {

	@Autowired
	// This means to get the bean which is auto-generated by Spring
	// We will use an employeeService for each
	EmployeeService employeeService;

	//	display list of employees
	@GetMapping("/")
	// This means that this method will be executed when user sends GET Requests to "/"
	// In our case, "http://localhost:8080/"
	public String viewHomePage(Model model) {

		//	We can use this attribute "listEmployees" to perform server-side rendering of the HTML with using Thymeleaf.
		//	We set all employees data to "listEmployees"
		model.addAttribute("listEmployees", employeeService.getAllEmployees());

		//		shows the index.html template:
		return "index";
	}

	//	showNewEmployeeForm
	@GetMapping("/showNewEmployeeForm")
	// This means that this method will be executed when user sends GET Requests to "/showNewEmployeeForm"
	// In our case,  "http://localhost:8080/showNewEmployeeForm"
	public String showNewEmployeeForm(Model model) {
		Employee employee = new Employee();

		// We can use this attribute "employee" to perform server-side rendering of the HTML with using Thymeleaf.
		model.addAttribute("employee", employee);

		//	shows the new_employee.html template:
		return "new_employee";
	}

	//	add an employee
	@PostMapping("/saveEmployee")
	// This means that this method will be executed when user sends POST Requests to "/saveEmployee"
	// In our case, "http://localhost:8080/saveEmployee"
	public String saveEmployee(@ModelAttribute("employee") Employee employee) {
		//	@ModelAttribute  binds the object called "employee" of request body from the POST request into the employee parameter of the saveEmployee() method.

		employeeService.saveEmployee(employee);

		// after save the employee data to database, redirect to "/"
		return "redirect:/";
	}

	//	show update form
	@GetMapping("/showFormForUpdate/{id}")
	// This means that this method will be executed when user sends GET Requests to "/showFormForUpdate/{employee's id}"
	// In our case, "http://localhost:8080/showFormForUpdate/{employee's id}"
	public String showUpdateForm(@PathVariable Long id, Model model) {
		// @PathVariable binds the {id} which the path of GET request contains into the id parameter of showUpdateForm() method.

		Employee employee = employeeService.getEmployeeById(id);

		//	We can use this attribute "employee" to perform server-side rendering of the HTML with using Thymeleaf.
		//	We set employee data to "employee"
		model.addAttribute("employee", employee);

		//	shows the update_employee.html template:
		return "update_employee";
	}

	//	delete the employee by id
	@GetMapping("/delete/{id}")
	// This means that this method will be executed when user sends GET Requests to "/delete/{employee's id}"
	//	In our case, "http://localhost:8080/delete/{employee's id}"
	public String deleteEmployeeById(@PathVariable Long id, Model model) {
		employeeService.deleteEmployeeById(id);

	//	after delete the employee data from database, redirect to "/"
		return "redirect:/";
	}
}

Step8 Create the HTML template files (Thymeleaf)

Next we are going to create HTML template files by using Thymeleaf. We use Materialize css which is a modern responsive front-end framework based on Material Design for styling our application.

Please create index.html, new_employee.html, update_employee.html at src/main/resources/templates with the following code.

*Comments in the code might be helpful for you to understand what's going on.

index.html

<!DOCTYPE html>
<!-- This is for using Thymeleaf -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Employee Management System</title>
<!-- Compiled and minified CSS -->
<link rel="stylesheet"
	href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

<!-- Compiled and minified JavaScript -->
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</head>
<body style="max-width: 960px; margin: 16px auto; padding: 16px">


	<h3>Employee List</h3>
	<!-- The link which sends GET request to "/showNewEmployeeForm"  -->
	<a th:href="@{/showNewEmployeeForm}"
		class="waves-effect waves-light btn">Add new employee</a>
	<div align="center" style="margin-top: 20px">
		<table class="responsive-table striped highlight centered">
			<thead>
				<tr>
					<th>First Name</th>
					<th>Last Name</th>
					<th>Email</th>
					<th>Actions</th>
				</tr>
			</thead>

			<tbody>
			<!-- You can acccess model attributes which are added in a Controller(EmployeeController.java) with ${attributeName}.
				 In this case, it is "${listEmployees}".
			     To show all employees data in this table, you need to use "th:each" in the thymeleaf template and iterate the employee of listEmployees -->
				<tr th:each="employee: ${listEmployees}">
					<td th:text="${employee.firstName}"></td>
					<td th:text="${employee.lastName}"></td>
					<td th:text="${employee.email}"></td>
					<td>
						<!-- The link which sends GET request to "/showFormForUpdate/{id}" (id is employee.id) -->
						<a th:href="@{/showFormForUpdate/{id}(id=${employee.id})}"
							class="waves-effect waves-light btn">Update</a>
					</td>
					<td>
						<!-- The link which sends GET request to "/delete/{id}" (id is employee.id)  -->
						<a th:href="@{/delete/{id}(id=${employee.id})}"
							class="waves-effect waves-light btn red litghten-2">Delete</a>
					</td>
				</tr>
			</tbody>
		</table>
	</div>
</body>
</html>

new_employee.html

<!DOCTYPE html>
<!-- This is for using Thymeleaf -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Employee Management System</title>
<!-- Compiled and minified CSS -->
<link rel="stylesheet"
	href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

<!-- Compiled and minified JavaScript -->
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</head>
<body style="max-width: 960px; margin: 16px auto; padding: 16px">
	<h3>Add New Employee</h3>
	<!-- The th:action="@{/saveEmployee}" expression directs the form to POST to the /saveEmployee endpoint.
		 The th:object="${employee}" expression declares the model object to use for collecting the form data.
		 The three form fields, expressed with th:field, correspond to the fields in the Employee object. -->
	<form th:action="@{/saveEmployee}" th:object="${employee}" method="post">
		<div class="row">
			<div class="input-field col s6">
				<input id="first_name" type="text" class="validate"
					th:field="*{firstName}"> <label for="first_name">First
					Name</label>
			</div>
			<div class="input-field col s6">
				<input id="last_name" type="text" class="validate"
					th:field="*{lastName}"> <label for="last_name">Last
					Name</label>
			</div>
		</div>
		<div class="row">
			<div class="input-field col s6">
				<input id="email" type="email" class="validate" th:field="*{email}">
				<label for="email">Email</label>
			</div>
		</div>
		<button type="submit" class="waves-effect waves-light btn">Add
			Employee</button>
	</form>
	<br>
	<!-- The link which sends GET request to "/"  -->
	<a th:href="@{/}"
		class="blue-text">Back</a>
</body>
</html>

update_employee.html

<!DOCTYPE html>
<!-- This is for using Thymeleaf -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Employee Management System</title>
<!-- Compiled and minified CSS -->
<link rel="stylesheet"
	href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

<!-- Compiled and minified JavaScript -->
<script
	src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</head>
<body style="max-width: 960px; margin: 16px auto; padding: 16px">
	<h3>Update Employee</h3>
	<!-- The th:action="@{/saveEmployee}" expression directs the form to POST to the /saveEmployee endpoint.
		 The th:object="${employee}" expression declares the model object to use for collecting the form data.
		 The three form fields, expressed with th:field, correspond to the fields in the Employee object. -->
	<form th:action="@{/saveEmployee}" th:object="${employee}" method="post">
		<div class="row">
		<input type="hidden" id="id"
					th:field="*{id}">
			<div class="input-field col s6">
				<input id="first_name" type="text" class="validate"
					th:field="*{firstName}"> <label for="first_name">First
					Name</label>
			</div>
			<div class="input-field col s6">
				<input id="last_name" type="text" class="validate"
					th:field="*{lastName}"> <label for="last_name">Last
					Name</label>
			</div>
		</div>
		<div class="row">
			<div class="input-field col s6">
				<input id="email" type="email" class="validate" th:field="*{email}">
				<label for="email">Email</label>
			</div>
		</div>
		<button type="submit" class="waves-effect waves-light btn">Update
			Employee</button>
	</form>
	<br>
	<!-- The link which sends GET request to "/"  -->
	<a th:href="@{/}"
		class="blue-text">Back</a>
</body>
</html>

Congratulations! You have just developed a Spring Boot application! Run your application and go to the http://localhost:8080/ and see what you just made!

Finally😎

Thank you for reading this post. Is this post useful for you? If it is, I am happy. I would be glad for any comments like impressions, bugs, what you don’t understand about this post from you. Don't hesitate to contact me.

Articles which I referenced

Share

If you like this post, please share!

Thank you for visiting my website. I would be glad if you like this website and continue having an interest in me.

Don't hesitate to contact me. 😎

avatat Satoru Akiyama

Other English Posts

| All Posts | English | Japanese |