SpringBoot+Jpa+Thymeleaf实现增删改查

2023-09-17 20:02:18

SpringBoot+Jpa+Thymeleaf实现增删改查

这篇文章介绍如何使用 Jpa 和 Thymeleaf 做一个增删改查的示例。

1、pom依赖

pom 包里面添加JpaThymeleaf 的相关包引用

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
	
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>spring-boot-jpa-thymeleaf-curd</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-jpa-thymeleaf-curd</name>
    <description>spring-boot-jpa-thymeleaf-curd</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <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>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2、application.properties中添加配置

spring.datasource.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
spring.thymeleaf.cache=false

其中propertiesspring.thymeleaf.cache=false是关闭 Thymeleaf 的缓存,不然在开发过程中修改页面不会

立刻生效需要重启,生产可配置为 true。

在项目 resources 目录下会有两个文件夹:static目录用于放置网站的静态内容如 cssjs图片

templates 目录用于放置项目使用的页面模板。

3、启动类

启动类需要添加 Servlet 的支持

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

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

4、数据库层代码

实体类映射数据库表

package com.example.model;

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

@Entity
public class User {

    @Id
    @GeneratedValue
    private long id;

    @Column(nullable = false, unique = true)
    private String userName;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private int age;

    public long getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

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

    public String getPassword() {
        return password;
    }

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

    public int getAge() {
        return age;
    }

    public User setAge(int age) {
        this.age = age;
        return this;
    }
}

5、 JpaRepository

package com.example.repository;

import com.example.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {

    User findById(long id);

    void deleteById(Long id);
}

继承 JpaRepository 类会自动实现很多内置的方法,包括增删改查,也可以根据方法名来自动生成相关 Sql。

6、业务层处理

Service 调用 Jpa 实现相关的增删改查,实际项目中 Service 层处理具体的业务代码。

package com.example.service;

import com.example.model.User;

import java.util.List;

public interface UserService {

    public List<User> getUserList();

    public User findUserById(long id);

    public void save(User user);

    public void edit(User user);

    public void delete(long id);

}
package com.example.service.impl;

import com.example.model.User;
import com.example.repository.UserRepository;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public List<User> getUserList() {
        return userRepository.findAll();
    }

    @Override
    public User findUserById(long id) {
        return userRepository.findById(id);
    }

    @Override
    public void save(User user) {
        userRepository.save(user);
    }

    @Override
    public void edit(User user) {
        userRepository.save(user);
    }

    @Override
    public void delete(long id) {
        userRepository.deleteById(id);
    }
}

7、控制层

package com.example.web;

import com.example.model.User;
import com.example.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import java.util.List;

@Controller
public class UserController {

    @Resource
    UserService userService;

    @RequestMapping("/")
    public String index() {
        return "redirect:/list";
    }

    @RequestMapping("/list")
    public String list(Model model) {
        List<User> users = userService.getUserList();
        model.addAttribute("users", users);
        return "user/list";
    }

    @RequestMapping("/toAdd")
    public String toAdd() {
        return "user/userAdd";
    }

    @RequestMapping("/add")
    public String add(User user) {
        userService.save(user);
        return "redirect:/list";
    }

    @RequestMapping("/toEdit")
    public String toEdit(Model model, Long id) {
        User user = userService.findUserById(id);
        model.addAttribute("user", user);
        return "user/userEdit";
    }

    @RequestMapping("/edit")
    public String edit(User user) {
        userService.edit(user);
        return "redirect:/list";
    }

    @RequestMapping("/delete")
    public String delete(Long id) {
        userService.delete(id);
        return "redirect:/list";
    }
}

Controller 负责接收请求,处理完后将页面内容返回给前端。

  • return "user/userEdit"; 代表会直接去 resources 目录下找相关的文件。

  • return "redirect:/list"; 代表转发到对应的 Controller,这个示例就相当于删除内容之后自动调整到

    list 请求,然后再输出到页面。

8、页面内容

list 列表 list.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>userList</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
</head>
<body class="container">
<br/>
<h1>用户列表</h1>
<br/><br/>
<div class="with:80%">
    <table class="table table-hover">
        <thead>
        <tr>
            <th>#</th>
            <th>User Name</th>
            <th>Password</th>
            <th>Age</th>
            <th>Edit</th>
            <th>Delete</th>
        </tr>
        </thead>
        <tbody>
        <tr  th:each="user : ${users}">
            <th scope="row" th:text="${user.id}">1</th>
            <td th:text="${user.userName}">neo</td>
            <td th:text="${user.password}">Otto</td>
            <td th:text="${user.age}">6</td>
            <td><a th:href="@{/toEdit(id=${user.id})}">edit</a></td>
            <td><a th:href="@{/delete(id=${user.id})}">delete</a></td>
        </tr>
        </tbody>
    </table>
</div>
<div class="form-group">
    <div class="col-sm-2 control-label">
        <a href="/toAdd" th:href="@{/toAdd}" class="btn btn-info">add</a>
    </div>
</div>

</body>
</html>

访问http://localhost:8080/,效果如下图所示:
在这里插入图片描述

<tr th:each="user : ${users}"> 这里会从 Controler 层 model set 的对象去获取相关的内容,th:each

示会循环遍历对象内容。

点击Add按钮会跳转到新增页面。

新增页面 userAdd.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>user</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
</head>
<body class="container">
<br/>
<h1>添加用户</h1>
<br/><br/>
<div class="with:80%">
    <form class="form-horizontal"   th:action="@{/add}"  method="post">
        <div class="form-group">
            <label for="userName" class="col-sm-2 control-label">userName</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="userName"  id="userName" placeholder="userName"/>
            </div>
        </div>
        <div class="form-group">
            <label for="password" class="col-sm-2 control-label" >Password</label>
            <div class="col-sm-10">
                <input type="password" class="form-control" name="password" id="password" placeholder="Password"/>
            </div>
        </div>
        <div class="form-group">
            <label for="age" class="col-sm-2 control-label">age</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="age"  id="age" placeholder="age"/>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <input type="submit" value="Submit" class="btn btn-info" />
                &nbsp; &nbsp; &nbsp;
                <input type="reset" value="Reset" class="btn btn-info" />
            </div>

        </div>
    </form>
</div>
</body>
</html>

在这里插入图片描述

填写数据并且点击Submit按钮,用户添加成功并且跳转到用户列表页面。

在这里插入图片描述

点击edit按钮跳转到用户修改页面。

修改页面 userEdit.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>user</title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}"></link>
</head>
<body class="container">
<br/>
<h1>修改用户</h1>
<br/><br/>
<div class="with:80%">
    <form class="form-horizontal"   th:action="@{/edit}" th:object="${user}"  method="post">
        <input type="hidden" name="id" th:value="*{id}" />
        <div class="form-group">
            <label for="userName" class="col-sm-2 control-label">userName</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="userName"  id="userName" th:value="*{userName}" placeholder="userName"/>
            </div>
        </div>
        <div class="form-group">
            <label for="password" class="col-sm-2 control-label" >Password</label>
            <div class="col-sm-10">
                <input type="password" class="form-control" name="password" id="password"  th:value="*{password}" placeholder="Password"/>
            </div>
        </div>
        <div class="form-group">
            <label for="age" class="col-sm-2 control-label">age</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="age"  id="age" th:value="*{age}" placeholder="age"/>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <input type="submit" value="Submit" class="btn btn-info" />
                &nbsp; &nbsp; &nbsp;
                <a href="/toAdd" th:href="@{/list}" class="btn btn-info">Back</a>
            </div>

        </div>
    </form>
</div>
</body>
</html>

在这里插入图片描述

修改用户的年龄为100然后点击Submit按钮提交修改。

然后跳转到用户列表页面发现数据修改了。

在这里插入图片描述

可以点击delete按钮删除用户。

删除之后跳转到用户列表页面。

在这里插入图片描述

这样一个使用 Jpa 和 Thymeleaf 的增删改查示例就完成了。

更多推荐

Flutter与Native通信原理剖析与实践

通信原理我们分几种场景来介绍Flutter和Native之间的通信。Native发送数据给FlutterFlutter发送数据给NativeFlutter发送数据给Native,然后Native回传数据给FlutterFlutter与Native通信机制在讲解Flutter与Native之间是如何传递数据之前,我们先了

UE4 C++ 使用第三方库(动态库) 详解

目录1代码共享的方式2使用三方库2.1准备一个动态库(包含.h;.lib;.dll)2.2创建一个UEC++工程2.3配置三方库1代码共享的方式在使用三方库之前,先介绍一下三方库的由来,以及为什么需要三方库。就从程序员共享代码成果开始讲述。1)三种共享方式:代码分发也就是代码共享的方式有三种:源码、动态库、静态库。源码

陕西省高级工程师职称评审条件

一.评审范围全省范围具有合法生产,经营手续的中小企业局和非公有制经济从事工程师工作专业技术人员和高技能人员,均可申报当年达到法定退休或已办退休的人员,不大参加职称评审。评审专业领域;机械,材料,冶金,电气,电子,信息通信,仪器仪表,能源动力,控制工程,计算机,自动化,人工智能,广播电视,建设,土木,水利,测绘,化工,地

GAN入门|第四篇:生成手势图像|可控制生成

🍨本文为🔗365天深度学习训练营中的学习记录博客🏡我的环境:语言环境:Python3.10.11编译器:JupyterNotebook深度学习框架:Pytorch2.0.1+cu118显卡(GPU):NVIDIAGeForceRTX4070👉考虑到大家算力有限,这里为大家提供我已经训练好生成器模型,大家可自行下

前端之webpck的优化

一、webpack的打包流程/webpack的机制/原理/webpack是怎么打包的1webpack是根据运行的指令来决定一个基本的业务流程2如果是build就是执行打包,如果是配合了devServer就是就行本地化的调试。两者其实在本质上没有太大区别,只是devServer会运行一个node服务器来进行本地化调试,打

构建工具Webpack简介

一、构建工具当我们习惯了Node中使用ES模块化编写代码以后,用原生的HTML、CSS、JS这些东西会感觉到各种不便。比如:不能放心的使用模块化规范(浏览器兼容性问题)、即使可以使用模块化规范也会面临模块过多时的加载问题。这时候我们就希望有一个工具能对代码进行打包,将多个模块打包成一个文件。这样一来即解决了兼容性问题,

pdf文件太大如何处理?教你pdf压缩简单方法

PDF文件过大,是很多人在使用PDF文件时都遇到过的一个常见问题,过大的PDF文件不仅会占用大量的存储空间,还会影响文件传输和处理效率,下面给大家总结了几个方法,帮助大家解决PDF文件过大的问题。方法一:嗨格式压缩大师这是一款专业的文件压缩工具,支持多种文件格式的压缩,包括PDF文件,它具有简单易用的界面,可以帮助用户

爬虫介绍及举例

爬虫(Webcrawler)指的是一种自动化程序,可以通过互联网上的URL,按照一定的规则,自动地抓取目标网站的数据,包括文字、图片、视频等,然后将这些数据进行处理、分析、存储或展示。举例来说,爬虫可以用于搜索引擎的抓取和索引,比如Google、百度等。当用户输入关键字进行搜索时,搜索引擎便会调用爬虫程序到网络上抓取相

Ebay易贝商品详情数据接口

易贝商品详情数据接口可以用于获取易贝商品详情信息,包括商品链接、状态、标题、简介、分类、商品图片、销量、价格等。获取易贝商品详情数据的接口是item_get,其请求参数为num_iid(EBAY商品ID),通过传入该参数可以获取商品详情数。易贝商品详情数据接口的具体使用方法如下:注册并获取API密钥。通过调用相应的AP

Docker Compose

文章目录简介compose文件一、文件简介二、version三、services1.build:2.image3.container_name4.ports5.command6.depends_on7.deploy8.networks9.volumes四、networks1.name2.driver3.attachab

加速老化测试目的是什么?

加速老化测试使用加速应力的组合来暴露产品设计和制造中的产品缺陷。这有助于提高产品可靠性并减少现场故障和保修费用。加速老化测试在环境室中进行,高温加速有效时间,通常与所有振动台结合使用,产生全轴振动。加速老化测试可分为高加速寿命测试(HALT)和高加速应力筛选(HASS)。这两种技术都使用远远超出产品正常工作条件的应力,

热文推荐