SpringBoot+SpringBootJPA+Thymeleaf实现基本CURD+分页

1.环境准备

  • JDK1.8
  • Maven3.6.0
  • SQLServer 2008R2
  • IDEA2020.1

2.数据库准备

-- 建库
CREATE DATABASE school;
-- 使用库
USE school;
-- 建表
create table student
(sno varchar(9) not null,
 sage int,
 sdept varchar(20),
 sname varchar(20) not null,
 ssex varchar(2),
 primary key (sno));

 -- 插入数据
INSERT INTO student VALUES
 ('032020460',20,'CS','killer','男'),
 ('032020441',19,'CS','武松','男'),
 ('032020451',21,'CS','李逵','男'),
 ('032020450',23,'CS','宋江','男'),
 ('032020420',20,'CS','晁盖','男'),
 ('032020461',22,'CS','王子鸣','男'),
 ('032020432',21,'CS','张一鸣','男'),
 ('032020430',19,'CS','曹操','男'),
 ('032020431',18,'CS','张红','女'),
 ('032020428',22,'CS','王佳','女'),
 ('032020421',18,'CS','李俊杰','男'),
 ('032020422',19,'CS','王小辉','男'),
 ('032020434',18,'CS','赵一','男'),
 ('032020443',21,'CS','张慧','女'),
 ('032020455',24,'CS','陈佳','女'),
 ('032020456',23,'CS','李惠','女'),
 ('032020458',22,'CS','周涛','男'),
 ('032020459',21,'CS','张明','男'),
 ('032020465',20,'CS','张蓓','女'),
 ('032020464',21,'CS','王光娜','女'),
 ('021830463',20,'MA','刘晓宇','男'),
 ('021830420',20,'MA','张家辉','男'),
 ('021830461',22,'MA','王小宇','男'),
 ('021830432',21,'MA','周泰','男'),
 ('021830430',19,'MA','宋义进','男'),
 ('021830431',18,'MA','张嘉雯','女'),
 ('021830428',22,'MA','陈小文','女'),
 ('021830421',18,'MA','刘涛','男'),
 ('021830422',19,'MA','王家辉','男'),
 ('021830434',18,'MA','江涛','男'),
 ('021830443',21,'MA','刘晓晓','女'),
 ('021830455',24,'MA','周惠','女'),
 ('021830456',23,'MA','李婷婷','女'),
 ('021830453',22,'MA','王嘉尔','男'),
 ('021830469',21,'MA','张角','男'),
 ('021830411',20,'MA','秦娇','女'),
 ('021830412',21,'MA','王玉','女'),
 ('021830466',20,'MA','张明杰','男'),
 ('021830436',18,'MA','江涛','男'),
 ('021830468',21,'MA','刘晓晓','女'),
 ('021830457',24,'MA','周惠','女'),
 ('021830439',23,'MA','李婷婷','女'),
 ('021830458',22,'MA','王嘉尔','男'),
 ('021830459',21,'MA','张角','男'),
 ('021830465',20,'MA','秦娇','女'),
 ('021830464',21,'MA','王玉','女'),
 ('021830445',20,'MA','张明杰','男'),
 ('011920434',18,'ME','王杰','男'),
 ('011920443',21,'ME','李晓','女'),
 ('011920455',24,'ME','张娇娇','女'),
 ('011920456',23,'ME','田婷婷','女'),
 ('011920458',22,'ME','尔东升','男'),
 ('011920459',21,'ME','周角','男'),
 ('011920465',20,'ME','倪妮','女'),
 ('011920464',21,'ME','李胜男','女'),
 ('011920463',20,'ME','张杰','男')

3.创建SpringBoot项目

创建项目比较简单,这里只给出maven,pom文件依赖。


<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.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.4.0version>
        <relativePath/> 
    parent>
    <groupId>cn.yugroupId>
    <artifactId>smartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>smname>
    <description>Demo project for Spring Bootdescription>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-jpaartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-devtoolsartifactId>
            <scope>runtimescope>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-configuration-processorartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        
        <dependency>
            <groupId>com.microsoft.sqlservergroupId>
            <artifactId>mssql-jdbcartifactId>
            <version>6.1.0.jre8version>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

project>

项目结构如下图:
SpringBoot+SpringBootJPA+Thymeleaf实现基本CURD+分页_第1张图片
图中的static中的error为存放的错误页面,css、js、fonts内容为bootstrap的源码文件。
项目配置文件为application.yuml,内容如下

server:
  port: 8080
  servlet:
    context-path: /sm
spring:
  datasource:
    url: jdbc:sqlserver://localhost:1433;databaseName=school
    username: sa
    password: 1234
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mode: HTML
    encoding: UTF-8
    cache: false
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

使用的数据库为SQLServer

4.启动类

SmApplication.java

package cn.yu.sm;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
public class SmApplication {

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

5.实体类

实体类Student.java

package cn.yu.sm.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

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

/**
 * 学生实体类
 */
@Table(name = "student")
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
public class Student {

    // 学号
    @Id
    @Column(name = "sno",length = 9)
    private String sno;

    // 姓名
    @Column(name = "sname",length = 20)
    private String sname;

    // 年龄
    @Column(name = "sage",length = 11)
    private Integer sage;

    // 性别
    @Column(name = "ssex",length = 2)
    private String ssex;

    // 系别
    @Column(name = "sdept",length = 20)
    private String sdept;
}

6.dao层

StudentRepository.java

package cn.yu.sm.dao;

import cn.yu.sm.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student,String> {
}

7.service层

package cn.yu.sm.service;

import cn.yu.sm.entity.Student;
import org.springframework.data.domain.Page;

/**
 * student 相关操作接口
 */
public interface StudentService {

    // 分页查询学生信息
    Page<Student> getStudentPage(int pageNum,int pageSize);

    // 根据学生学号查询学生信息
    Student findStudentBySno(String sno);

    // 保存学生信息
    void save(Student student);

    // 更新学生信息
    void update(Student student);

    // 根据学号删除学生
    void delete(String sno);

    // 统计学生数量
    long count();
}

StudentServiceImpl.java

package cn.yu.sm.service.impl;

import cn.yu.sm.dao.StudentRepository;
import cn.yu.sm.entity.Student;
import cn.yu.sm.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;


@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    StudentRepository studentRepository;

    // 分页查询学生信息实现
    @Override
    public Page<Student> getStudentPage(int pageNum, int pageSize) {
        // 创建一个排序对象 根据学生年龄升序
        Sort sort = Sort.by(Sort.Direction.ASC,"sage");
        // 创建分页对象
        PageRequest pageable = PageRequest.of(pageNum, pageSize, sort);
        // 调用dao 分页查询
        Page<Student> students = studentRepository.findAll(pageable);
        return students;
    }

    // 根据学号查询学生信息实现
    @Override
    public Student findStudentBySno(String sno) {
        return studentRepository.findById(sno).get();
    }

    // 保存学生信息实现
    @Override
    public void save(Student student) {
        studentRepository.save(student);
    }

    // 更新学生信息实现
    @Override
    public void update(Student student) {
        studentRepository.save(student);
    }

    // 根据学号删除学生信息实现
    @Override
    public void delete(String sno) {
        studentRepository.deleteById(sno);
    }

    // 统计学生总数
    @Override
    public long count() {
        return studentRepository.count();
    }
}

8.controller层

StudentController.java

package cn.yu.sm.controller;

import cn.yu.sm.entity.Student;
import cn.yu.sm.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Iterator;

@Controller
public class StudentController {

    @Autowired
    StudentService studentService;

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

    // 处理分页请求
    @RequestMapping("/list")
    public String list(Model model,
                       @RequestParam(value = "pageNum", defaultValue = "0") int pageNum,
                       @RequestParam(value = "pageSize", defaultValue = "10") int pageSize) {
        System.out.println("======分页查询========");
        Page<Student> students = studentService.getStudentPage(pageNum, pageSize);
        System.out.println("总页数:" + students.getTotalPages());
        System.out.println("当前页:" + pageNum);
        // 打印数据
        System.out.println("分页数据如下");
        Iterator<Student> iterator = students.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        // 统计学生数量
        long count = studentService.count();
        // 将数据组装到模型中
        model.addAttribute("students",students);
        model.addAttribute("cnt",count);
        return "student/list";
    }

    // 处理删除请求
    @RequestMapping("/delete")
    public String delete(String sno){
        studentService.delete(sno);
        return "redirect:/";
    }

    // 处理添加请求
    @RequestMapping("/toAdd")
    public String toAdd(Model model){
        model.addAttribute("isUpdate",false);
        return "student/update";
    }

    // 处理修改请求
    @RequestMapping("/toEdit")
    public String toEdit(Model model,String sno){
        // 查询学生信息
        Student student = studentService.findStudentBySno(sno);
        // 封装数据
        model.addAttribute("student",student);
        model.addAttribute("isUpdate",true);
        return "student/update";
    }

    // 添加学生
    @RequestMapping("/add")
    public String add(Student student){
        studentService.save(student);
        return "redirect:/";
    }
}

9.utils工具类

package cn.yu.sm.utils;

import java.util.HashMap;
import java.util.Map;

/**
 * 根据系简写 获取系的中文名称
 */
public class DeptUtils {

    private static Map<String,String> depts = new HashMap<>();

    static {
        depts.put("CS","计算机系");
        depts.put("PHY","物理系");
        depts.put("MA","数学系");
        depts.put("ME","医学系");
        depts.put("CH","中文系");
        depts.put("JD","法学系");
        depts.put("ART","艺术系");
    }

    public static String getName(String dept){
        return depts.get(dept);
    }
}

10.前端

在resource目录下的templates目录下创建一个student目录,然后创建list.html用于展示学生信息,update.list为修改和添加学生信息。

bootstrap的相关文件可以到bootstrap官网下载。

list.html


<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>学生列表title>
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}">link>
    <style>
        th {
            text-align: center;
        }
    style>
head>
<body class="container">
<br/>
<div style="text-align: center;color: #4cae4c;">
    <h1>学生列表h1>
div>
<br/>
<hr/>
<div>
    学生总数:<span th:text="${cnt}">span>
    <a style="float: right;" href="/sm/toAdd" th:href="@{/toAdd}" class="btn btn-success btn-sm">添加a>
div>
<div class="with:80%" style="text-align: center;">
    <table class="table table-bordered">
        <thead>
        <tr>
            <th>#th>
            <th>学号th>
            <th>姓名th>
            <th>年龄th>
            <th>性别th>
            <th>系别th>
            <th>操作th>
        tr>
        thead>
        <tbody>
        <tr th:each="student : ${students}">
            <th scope="row" th:text="${studentStat.index + 1}">1th>
            <td th:text="${student.sno}">td>
            <td th:text="${student.sname}">td>
            <td th:text="${student.sage}">td>
            <td th:text="${student.ssex}">td>
            <td th:text="${T(cn.yu.sm.utils.DeptUtils).getName(student.sdept)}">td>
            <td>
                <a class="btn btn-sm btn-warning" th:href="@{/toEdit(sno=${student.sno})}">修改a>
                <a class="btn btn-sm btn-danger" th:href="@{/delete(sno=${student.sno})}">删除a>
            td>
        tr>
        tbody>
    table>
div>

<div class="modal-footer">

    <ul class="pagination pagination-sm">
        
        
        <li>
            <a th:href="'/sm/list?pageNum=0'">首页a>
        li>
        
        <li th:if="${students.hasPrevious()}">
            <a th:href="'/sm/list?pageNum=' + ${students.previousPageable().getPageNumber()}" th:text="上一页">a>
        li>
        
        <li th:each="pageNum:${#numbers.sequence(0, students.getTotalPages() - 1)}">
            <a th:href="'/sm/list?pageNum=' + ${pageNum}" th:text="${pageNum + 1}"
               th:if="${pageNum ne students.pageable.getPageNumber()}">a>
            <a th:href="'/sm/list?pageNum=' + ${pageNum}" th:text="${pageNum + 1}"
               th:if="${pageNum eq students.pageable.getPageNumber()}"
               th:style="'font-weight:bold;background: #6faed9;'">a>
        li>
        
        <li th:if="${students.hasNext()}">
            <a th:href="'/sm/list?pageNum=' + ${students.nextPageable().getPageNumber()}" th:text="下一页">a>
        li>
        
        <li>
            <a th:href="'/sm/list?pageNum=' + ${students.getTotalPages() - 1}">尾页a>
        li>
    ul>
div>
body>
html>

update.html


<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" th:href="@{/css/bootstrap.css}">
    <title th:text="${isUpdate?'修改学生信息':'添加学生'}">title>
head>
<body>
    <div style="text-align: center;color: #4cae4c;" class="top">
        <h1 th:text="${isUpdate?'修改学生信息':'添加学生'}">h1>
    div>
    <hr>
    <div style="margin: 0 auto;width: 30%;">
        <form th:action="@{/add}" method="post">
            <div class="form-group">
                <label for="sno">学号label>
                <input type="text" th:value="${student!=null?student.sno:''}" class="form-control" id="sno" name="sno" placeholder="032020...">
            div>
            <div class="form-group">
                <label for="sname">姓名label>
                <input type="text" th:value="${student!=null?student.sname:''}" class="form-control" id="sname" name="sname" placeholder="姓名">
            div>
            <div class="form-group">
                <label for="sage">年龄label>
                <input type="text" th:value="${student!=null?student.sage:''}" class="form-control" id="sage" name="sage" placeholder="18">
            div>
            <div class="form-group">
                <label>性别label><br>
                <label class="radio-inline">
                    <input type="radio" th:checked="${student!=null?#strings.equals(student.ssex,''):false}" id="inlineRadio1" name="ssex" value="">label>
                <label class="radio-inline">
                    <input type="radio" th:checked="${student!=null?#strings.equals(student.ssex,''):false}" id="inlineRadio2" name="ssex" value="">label>
            div>
            <div class="form-group">
                <label>系别label><br>
                <select name="sdept" class="form-control">
                    <option value="CS"  th:selected="${student!=null?#strings.equals(student.sdept,'CS'):''}">计算机系option>
                    <option value="PHY" th:selected="${student!=null?#strings.equals(student.sdept,'PHY'):''}">物理系option>
                    <option value="MA"  th:selected="${student!=null?#strings.equals(student.sdept,'MA'):''}">数学系option>
                    <option value="ME"  th:selected="${student!=null?#strings.equals(student.sdept,'ME'):''}">医学系option>
                    <option value="CH"  th:selected="${student!=null?#strings.equals(student.sdept,'CH'):''}">中文系option>
                    <option value="JD"  th:selected="${student!=null?#strings.equals(student.sdept,'JD'):''}">法学系option>
                    <option value="ART" th:selected="${student!=null?#strings.equals(student.sdept,'ART'):''}">艺术系option>
                select>
            div>
            <div style="text-align: center;">
                <button th:text="${isUpdate?'修改':'添加'}" type="submit" class="btn btn-default btn-success">添加button>
                   <button th:if="${!isUpdate}" type="reset" class="btn btn-default btn-warning">重置button>
            div>
        form>
    div>
body>
html>

10.运行效果

列表页http://localhost:8080/sm/list
SpringBoot+SpringBootJPA+Thymeleaf实现基本CURD+分页_第2张图片
添加学生http://localhost:8080/sm/toAdd
SpringBoot+SpringBootJPA+Thymeleaf实现基本CURD+分页_第3张图片
修改学生http://localhost:8080/sm/toEdit?sno=021830421
SpringBoot+SpringBootJPA+Thymeleaf实现基本CURD+分页_第4张图片
项目源码已经上传码云,地址为:https://gitee.com/wang_yu666/springboot-curd
注意码云上的项目使用的数据库为MySQL5.7,在建表的时候需要设置字符集为utf8,不然插入中文时会出现无法插入的问题。

你可能感兴趣的:(Java,java,spring,boot,bootstrap)