1. 概述

在开发中,针对 JPA 实体实现 DAO 层的 CRUD(增删改查)功能往往是一个重复且耗时的过程。我们通常希望避免这种机械性工作。

幸运的是,Spring Boot 提供了基于标准 JPA 的 CRUD Repository 层,可以极大简化这一过程。

本教程将带你一步步使用 Spring Boot 和 Thymeleaf 构建一个完整的 CRUD Web 应用程序。

2. Maven 依赖配置

为了简化依赖管理和版本控制,我们使用 spring-boot-starter-parent 作为父项目。

因此,在 pom.xml 中我们无需显式指定依赖版本(除了 Java 版本):

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</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-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
</dependencies>

3. 领域层设计

依赖配置完毕后,我们来实现一个简单的领域层。

为了演示方便,我们只定义一个 User 实体类:

@Entity
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    
    @NotBlank(message = "Name is mandatory")
    private String name;
    
    @NotBlank(message = "Email is mandatory")
    private String email;

    // 标准构造函数 / setter / getter / toString 省略
}

⚠️ 注意:使用了 @Entity 注解,这样 Hibernate(JPA 的实现)就可以对这个实体进行 CRUD 操作了。

另外,我们对 nameemail 字段使用了 @NotBlank 注解约束,这意味着在保存或更新前可以借助 Hibernate Validator 做字段校验。

如需了解更多,可参考 Bean Validation 教程

4. Repository 层

目前我们的应用还啥也干不了,不过马上就好。

Spring Data JPA 提供了一种非常简洁的方式来实现 JPA 的 Repository(也就是 DAO 模式的实现)。

它是 spring-boot-starter-data-jpa 的核心组件,通过在 JPA 实现之上封装了一层强大的抽象,让我们无需从零开始编写 DAO 实现。

✅ 要为 User 实体提供基础的 CRUD 功能,只需继承 CrudRepository 接口:

@Repository
public interface UserRepository extends CrudRepository<User, Long> {}

就是这么简单!Spring Data JPA 会自动为我们实现 CRUD 方法。

5. 控制层设计

借助 Spring Data JPA 的抽象层,我们可以轻松在 Web 层添加 CRUD 功能。

我们只需要一个 Controller 来处理 GET 和 POST 请求,并调用 UserRepository 即可。

以下是 Controller 的部分核心方法:

@Controller
public class UserController {
    
    @GetMapping("/signup")
    public String showSignUpForm(User user) {
        return "add-user";
    }
    
    @PostMapping("/adduser")
    public String addUser(@Valid User user, BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "add-user";
        }
        
        userRepository.save(user);
        return "redirect:/index";
    }

    // 其他 CRUD 方法略
}

显示用户列表

@GetMapping("/index")
public String showUserList(Model model) {
    model.addAttribute("users", userRepository.findAll());
    return "index";
}

编辑用户表单

@GetMapping("/edit/{id}")
public String showUpdateForm(@PathVariable("id") long id, Model model) {
    User user = userRepository.findById(id)
      .orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
    
    model.addAttribute("user", user);
    return "update-user";
}

更新 & 删除用户

@PostMapping("/update/{id}")
public String updateUser(@PathVariable("id") long id, @Valid User user, 
  BindingResult result, Model model) {
    if (result.hasErrors()) {
        user.setId(id);
        return "update-user";
    }
        
    userRepository.save(user);
    return "redirect:/index";
}
    
@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") long id, Model model) {
    User user = userRepository.findById(id)
      .orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
    userRepository.delete(user);
    return "redirect:/index";
}

6. 视图层构建

我们已经有了功能完整的 Controller,但还差一步:视图层。

src/main/resources/templates 目录下创建以下 Thymeleaf 模板文件:

新增用户表单 add-user.html

<form action="#" th:action="@{/adduser}" th:object="${user}" method="post">
    <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>
    <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>
    <input type="submit" value="Add User">   
</form>

更新用户表单 update-user.html

<form action="#" 
  th:action="@{/update/{id}(id=${user.id})}" 
  th:object="${user}" 
  method="post">
    <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>
    <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>
    <input type="submit" value="Update User">   
</form>

用户列表页面 index.html

<div th:switch="${users}">
    <h2 th:case="null">No users yet!</h2>
        <div th:case="*">
            <h2>Users</h2>
            <table>
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Edit</th>
                        <th>Delete</th>
                    </tr>
                </thead>
                <tbody>
                <tr th:each="user : ${users}">
                    <td th:text="${user.name}"></td>
                    <td th:text="${user.email}"></td>
                    <td><a th:href="@{/edit/{id}(id=${user.id})}">Edit</a></td>
                    <td><a th:href="@{/delete/{id}(id=${user.id})}">Delete</a></td>
                </tr>
            </tbody>
        </table>
    </div>      
    <p><a href="/signup">Add a new user</a></p>
</div>

💡 提示:模板结构简单,功能为主。如需美化界面,可引入 BootstrapShards 等 UI 框架。

7. 启动应用

最后一步,定义应用入口:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

运行项目后,访问 http://localhost:8080 即可看到一个完整的用户管理界面。

✅ 功能包括:新增用户、编辑、删除、列表展示。

8. 总结

本文带你从零开始,使用 Spring Boot 和 Thymeleaf 构建了一个完整的 CRUD Web 应用。

所有代码示例均可在 GitHub 获取。


原始标题:Spring Boot CRUD Application with Thymeleaf