introduction h2>
this article introduces a simple CRUD application using spring boot and Thymeleaf.
create Maven project
here to create a maven-based project using intellij community edition
overall architecture
Add Maven dependencies
database selected H2 lightweight database, convenient configuration, default configuration data written into memory, restart service lost, configuration data can be written to the file.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<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>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>
h2> Domain layer
The
layer defines the entity class for data interaction. Here we define the Student class.
package com.springbootcrud.entity;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@NotBlank(message = "Name is mandatory")
@Column(name = "name")
private String name;
@NotBlank(message = "Email is mandatory")
@Column(name = "email")
private String email;
@Column(name = "phoneNo")
private long phoneNo;
public Student() {
}
public Student(String name, String email) {
this.name = name;
this.email = email;
}
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 getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public long getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(long phoneNo) {
this.phoneNo = phoneNo;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", phoneNo=" + phoneNo +
'}';
}
}
repository layer h2>
is the persistence layer that interacts with the database. Here, the implementation of adding, deleting, modifying and checking entity classes in the database is specifically implemented. Here, we inherit the corresponding classes of the spring data framework instead of implementing the Dao layer implementation method by ourselves.
package com.springbootcrud.repository;
import com.springbootcrud.entity.Student;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface StudentRepository extends CrudRepository<Student, Long> {
List<Student> findByName(String Name);
}
h2> controller layer
this layer is responsible for processing the user’s input and returning the correct response back to the user.
package com.springbootcrud.controller;
import com.springbootcrud.entity.Student;
import com.springbootcrud.repository.StudentRepository;
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;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@Controller
@RequestMapping("/students/")
public class StudentController {
private final StudentRepository studentRepository;
@Autowired
public StudentController(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
@GetMapping("signup")
public String showSignUpForm(Student student) {
return "add-student";
}
@GetMapping("list")
public String showUpdateForm(Model model) {
System.out.println(studentRepository.findAll());
model.addAttribute("students", studentRepository.findAll());
return "index";
}
@PostMapping("add")
public String addStudent(@Valid Student student, BindingResult result, Model model) {
if (result.hasErrors()) {
return "add-student";
}
studentRepository.save(student);
return "redirect:list";
}
@GetMapping("edit/{id}")
public String showUpdateForm(@PathVariable("id") final long id, Model model) {
Student student = studentRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid student Id:" + id));
model.addAttribute("student", student);
return "update-student";
}
@PostMapping("update/{id}")
public String updateStudent(@PathVariable("id") long id, @Valid Student student, BindingResult result, Model model) {
if (result.hasErrors()) {
student.setId(id);
return "update-student";
}
studentRepository.save(student);
model.addAttribute("students", studentRepository.findAll());
return "index";
}
@GetMapping("delete/{id}")
public String deleteStudent(@PathVariable("id") long id, Model model) {
Student student = studentRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid student id:" + id));
studentRepository.delete(student);
model.addAttribute("students", studentRepository.findAll());
return "index";
}
}
h2> View layer
user sees the specific web page view, combined with Thymeleaf populated data, shown to the user
add-student.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Add User</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
<!-- <link rel="stylesheet" href="../css/shards.min.css"> -->
</head>
<body>
<div class="container my-5">
<h3>Add Student</h3>
<div class="card">
<div class="card-body">
<div class="col-md-10">
<form action="#" th:action="@{/students/add}" th:object="${student}" method="post">
<div class="row">
<div class="form-group col-md-8">
<label for="name" class="col-form-label">Name</label> <input type="text" th:field="*{name}" class="form-control" id="name" placeholder="Name"> <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="email" class="col-form-label">Email</label> <input type="text" th:field="*{email}" class="form-control" id="email" placeholder="Email"> <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="phoneNo" class="col-form-label">Phone No</label> <input type="text" th:field="*{phoneNo}" class="form-control" id="phoneNo" placeholder="PhoneNo"> <span th:if="${#fields.hasErrors('phoneNo')}" th:errors="*{phoneNo}" class="text-danger"></span>
</div>
<div class="col-md-6">
<input type="submit" class="btn btn-primary" value="Add Student">
</div>
<div class="form-group col-md-8"></div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Users</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
<!-- <link rel="stylesheet" href="../css/shards.min.css"> -->
</head>
<body>
<div class="container my-2">
<div class="card">
<div class="card-body">
<div th:switch="${students}" class="container my-5">
<p class="my-5">
<a href="/students/signup" class="btn btn-primary"><i class="fas fa-user-plus ml-2"> Add Student</i></a>
</p>
<div class="col-md-10">
<h2 th:case="null">No Students yet!</h2>
<div th:case="*">
<table class="table table-striped table-responsive-md">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone No</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr th:each="student : ${students}">
<td th:text="${student.name}"></td>
<td th:text="${student.email}"></td>
<td th:text="${student.phoneNo}"></td>
<td><a th:href="@{/students/edit/{id}(id=${student.id})}" class="btn btn-primary"><i class="fas fa-user-edit ml-2"></i></a></td>
<td><a th:href="@{/students/delete/{id}(id=${student.id})}" class="btn btn-primary"><i class="fas fa-user-times ml-2"></i></a></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
update-student.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Update User</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
<!-- <link rel="stylesheet" href="../css/shards.min.css"> -->
</head>
<body>
<div class="container my-5">
<h3>Update Student</h3>
<div class="card">
<div class="card-body">
<div class="col-md-8">
<form action="#" th:action="@{/students/update/{id}(id=${student.id})}" th:object="${student}" method="post">
<div class="row">
<div class="form-group col-md-6">
<label for="name" class="col-form-label">Name</label> <input type="text" th:field="*{name}" class="form-control" id="name" placeholder="Name"> <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="email" class="col-form-label">Email</label> <input type="text" th:field="*{email}" class="form-control" id="email" placeholder="Email"> <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<label for="phoneNo" class="col-form-label">Phone No</label> <input type="text" th:field="*{phoneNo}" class="form-control" id="phoneNo" placeholder="PhoneNo"> <span th:if="${#fields.hasErrors('phoneNo')}" th:errors="*{phoneNo}" class="text-danger"></span>
</div>
<div class="form-group col-md-8">
<input type="submit" class="btn btn-primary" value="Update Student">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
run springboot application
program run entry.
package com.springbootcrud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
execution effect
p>
Read More:
- Spring Boot Thymeleaf ERROR 8592 org.thymeleaf.TemplateEngine
- Encapsulation of adding, deleting and modifying database by JDBC
- Spring boot problem 1: error reporting life processing instructions for building a spring boot project
- Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.4.0:repackage failed
- Simple use of namedparameterjdbctemplate of spring
- Add PageHelper spring boot starter dependency to springboot and report an error
- Spring boot problem solving record (1)
- The spring boot project directly replaces the referenced jar package
- spring boot Whitelabel Error Page
- Spring boot running appears java.lang.IllegalStateException : Failed to load ApplicationContext
- Spring boot prompt could not resolve placeholder in string value
- Spring boot does not take effect when using @ size to verify a single set parameter of the control layer
- Spring boot integrates Mongo to solve some common connection and permission problems. Docker compose installs Mongo
- Spring boot integrates es cluster error report collection
- spring boot-beans in application context form a cycle
- 13.2 spring boot start error: whitelabel error page
- Specify the configuration file when the spring boot command starts
- Failure of spring boot configuration server port
- Spring boot JPA Repository exception Validation failed for query for method
- Solution to the problem of spring boot running test class error creating bean with name ‘serverendpoint exporter’ defined