Springboot +JPA+thymeleaf+MySQL+BootStrap制作订单管理系统

前言:

用Springboot +JPA+thymeleaf+MySQL+BootStrap 部署了一个订单管理系统,实现了 添加设备、删除设备、更新设备、查找设备、分页、排序等功能,项目内分有不同的包,也就是层,下面我将对每层进行解释。
BootStrap官网

1.创建项目

在这里插入图片描述
在这里插入图片描述

1.1 项目结构

在这里插入图片描述

1.2 在application.properties配置数据库

spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
                                    #localhost:3306为mysql的host和port tesstdb就是连接的庶几乎库名称
#mysql用户名
spring.datasource.username= root
#登入mysql的密码
spring.datasource.password= 123456

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# for Spring Boot 2
# spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect

# for Spring Boot 3
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQLDialect

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

#?????hibernate-sql
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE



2.model模型层

package com.example.mvcorders.model;

import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
@Table(name = "orders")
public class Orders {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    //订单id
    @Column(name = "order_id")
    private Long orderID;

    //时间
    @Column(name = "time")
    private String time;

    //收件人
    @Column(name = "consignee")
    private String consignee;

    //收件地址
    @Column(name = "addr")
    private String addr;

    //订单状态
    @Column(name = "status")
    private String status;
}

3.repository层

此层只定义了一个接口,而且此接口继承了JpaRepository接口,JpaRepository接口内有很多方法,可供接下来的使用,因为JpaRepository接口里并不一定有我想要的功能的方法,这里我创建了一个模糊查询,可以通过status状态这个属性,查询到相关的所有信息

package com.example.mvcorders.repository;

import com.example.mvcorders.model.Orders;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface OrdersRepository extends JpaRepository<Orders,Long> {
    @Query("select e from Orders e where e.status like %:status%")
    List<Orders> findByStatus(@Param("status") String status);
}

4.service 业务层

业务层分别有两部分,一个是接口,一个是接口的实现类

4.1OrdersService接口

接口里负责构建方法,但没有实体,方法的实体由继承此接口的类重写,每个方法指定要实现什么功能

package com.example.mvcorders.service;

import com.example.mvcorders.model.Orders;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

public interface OrdersService {
    //获取所有订单
    List<Orders> getOrders();

    //新增/更新一个订单
    void saveOrders(Orders orders);

    //获取指定ID的订单
    Orders getOrdersById(long id);

    //删除指定ID的订单
    void deleteOrdersById(long id);

    //通过指定状态查询信息
    List<Orders> findByStatus(String status);

    //分页
    Page<Orders> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection);
}

4.2 OrdersServicelmpl类

此类需要继承OrdersService接口并实现父类方法

package com.example.mvcorders.service;

import com.example.mvcorders.model.Orders;
import com.example.mvcorders.repository.OrdersRepository;
import org.aspectj.weaver.ast.Or;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class OrdersServicelmpl implements OrdersService{
    @Autowired
    private OrdersRepository ordersRepository;

    @Override   //返回所有信息
    public List<Orders> getOrders() {
        return ordersRepository.findAll();
    }

    @Override   //添加信息
    public void saveOrders(Orders orders) {
        this.ordersRepository.save(orders);
    }

    @Override   //通过id查找信息
    public Orders getOrdersById(long id) {
        Optional<Orders> optional = ordersRepository.findById(id);

        Orders orders = null;
        if (optional.isPresent()){
            orders = optional.get();
        }else {
            throw new RuntimeException("找不到订单ID:"+id);
        }
        return orders;
    }

    @Override   //通过byID删除信息
    public void deleteOrdersById(long id) {
        this.ordersRepository.deleteById(id);
    }

    @Override   //通过状态查询信息
    public List<Orders> findByStatus(String status) {
        return ordersRepository.findByStatus(status);
    }


    @Override   //排序分页
    public Page<Orders> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection) {
        Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name())
                ? Sort.by(sortField).ascending()
                : Sort.by(sortField).descending();

        //根据页号/每页记录数/排序依据返回某指定页面数据。
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);
        return this.ordersRepository.findAll(pageable);
    }
}

5.Controller控制层

此层只定义了一个类,用于接收参数,调用Service层的方法的返回值进行封装,返回数据/返回页面,路由。

package com.example.mvcorders.controller;

import com.example.mvcorders.model.Orders;
import com.example.mvcorders.service.OrdersService;
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.*;

import java.util.List;

@Controller
public class OrdersController {

    @Autowired
    private OrdersService ordersService;

    @GetMapping("/")
    public String viewHomePage(Model model) {
        return findPaginated(1, "status", "asc", model);
    }

    //添加数据
    @GetMapping("/showNewOrdersForm")
    public String showNewOrdersForm(Model model) {
        // 创建模型属性来绑定表单数据
        Orders orders = new Orders();
        //addAttribute方法用于向模型(Model)中添加属性(Attribute)供视图(View)使用。
        //创建了一个名为orders,值为一个orders对象的属性
        model.addAttribute("orders", orders);
        //返回到net_orders 视图
        return "new_orders";
    }

    // 将员工保存到数据库
    @PostMapping("/saveOrders")
    public String saveOrders(@ModelAttribute("orders") Orders orders) {

        ordersService.saveOrders(orders);
        return "redirect:/";
    }

    //更新数据
    @GetMapping("/showFormForUpdate/{id}")
    //@PathVariable 注解来获取在 URL 中动态传递的参数
    public String showFormForUpdate(@PathVariable(value = "id") long id, Model model) {

        // 从服务中获取员工
        Orders orders = ordersService.getOrdersById(id);

        // 将employee设置为模型属性以预填充表单
        model.addAttribute("orders", orders);
        return "update_orders";
    }

    //删除数据
    @GetMapping("/deleteOrders/{id}")
    public String deleteOrders(@PathVariable(value = "id") long id) {

        // call delete employee method
        this.ordersService.deleteOrdersById(id);
        return "redirect:/";
    }

    //通过状态查询
    @GetMapping("/find")
    public String findStatus(@RequestParam("status") String status, Model model){
        List<Orders> byStatus = ordersService.findByStatus(status);
        model.addAttribute("byStatus", byStatus);
        return "find_status";
    }

    //分页
    @GetMapping("/page/{pageNo}")
    public String findPaginated(@PathVariable (value = "pageNo") int pageNo,
                                //@RequestParam 注解可以将这些查询参数绑定到处理器方法的参数上,从而方便获取和处理这些参数。
                                @RequestParam("sortField") String sortField,
                                @RequestParam("sortDir") String sortDir,
                                Model model) {
        int pageSize = 8;

        Page<Orders> page = ordersService.findPaginated(pageNo, pageSize, sortField, sortDir);

        List<Orders> listOrders = page.getContent();

        model.addAttribute("currentPage", pageNo);
        model.addAttribute("totalPages", page.getTotalPages());
        model.addAttribute("totalItems", page.getTotalElements());

        model.addAttribute("sortField", sortField);
        model.addAttribute("sortDir", sortDir);
        model.addAttribute("reverseSortDir", sortDir.equals("asc") ? "desc" : "asc");

        model.addAttribute("listOrders", listOrders);
        return "index";
    }
}

6.HTML

6.1 Index.html部分

此部分用于是主体页面的代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Orders Management System</title>

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
</head>

<body>

<div class="container my-2 border">
  <h1 class="text-center">Orders Management System</h1>

    <nav>	<!--设置搜索栏-->
        <form style="float: right;" th:action="@{/find}" method="get">
            <input id="status" type="text" name="status" placeholder="Search...">
            <button type="submit" class="btn-dark">Search</button>
        </form>
    </nav>

    <!--  th:href 链接地址-->
    <a th:href = "@{/showNewOrdersForm}" class="btn btn-dark btn-sm mb-3"> Add Orders </a>

    <table border="1" class = "table table-condensed table-dark table-hover text-info table-bordered table-hover text-center">
      <thead>
          <tr>
              <th>
                  <a th:href="@{'/page/' + ${currentPage} + '?sortField=orderID&sortDir=' + ${reverseSortDir}}">
                      orderID</a>
              </th>
              <th>
                  <a th:href="@{'/page/' + ${currentPage} + '?sortField=time&sortDir=' + ${reverseSortDir}}">
                      time</a>
              </th>
              <th>
                  <a th:href="@{'/page/' + ${currentPage} + '?sortField=consignee&sortDir=' + ${reverseSortDir}}">
                      consignee</a>
              </th>
              <th>
                  <a th:href="@{'/page/' + ${currentPage} + '?sortField=addr&sortDir=' + ${reverseSortDir}}">
                      addr</a>
              </th>
              <th>
                  <a th:href="@{'/page/' + ${currentPage} + '?sortField=status&sortDir=' + ${reverseSortDir}}">
                      status</a>
              </th>
              <th>Actions</th>
          </tr>
      </thead>

    <tbody>
    <!--    th:each 元素遍历-->
    <tr th:each="orders : ${listOrders}">
      <!--th:text 用于指定标签显示的内容-->
      <td th:text="${orders.orderID}"></td>
      <td th:text="${orders.time}"></td>
      <td th:text="${orders.consignee}"></td>
      <td th:text="${orders.addr}"></td>
      <td th:text="${orders.status}"></td>

      <!--定位到controller层下-->
      <td>
        <a th:href="@{/showFormForUpdate/{id}(id=${orders.id})}" class="btn btn-primary ">更新</a>
        <a th:href="@{/deleteOrders/{id}(id=${orders.id})}" class="btn btn-danger">删除</a>
      </td>
    </tr>
    </tbody>
  </table>

<!--   th:if 条件判断,如果为真-->
  <div th:if = "${totalPages > 1}">

    <div class = "row col-sm-10">
      <!--显示一共有几行数据-->
      <div class = "col-sm-3">
        Total Rows: [[${totalItems}]]
      </div>

      <!--显示页数-->
      <div class = "col-sm-5">
        <span th:each="i: ${#numbers.sequence(1, totalPages)}">
            <a th:if="${currentPage != i}" th:href="@{'/page/' + ${i}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">[[${i}]]</a>
            <span th:unless="${currentPage != i}">[[${i}]]</span>  &nbsp; &nbsp;
        </span>
      </div>

      <!--切换到下一页-->
      <div class = "col-sm-1">
        <a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${currentPage + 1}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">Next</a>
        <span th:unless="${currentPage < totalPages}">Next</span>
      </div>

      <!--切换到最后一页-->
      <div class="col-sm-1">
        <a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${totalPages}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">Last</a>
        <span th:unless="${currentPage < totalPages}">Last</span>
      </div>

    </div>
  </div>

</div>

</body>
</html>






效果:
在这里插入图片描述

6.2 new_orders.html部分

此页面是添加数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Order Management System</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
</head>
<body>

<div class="container my-2 " >
    <h1 class="text-center" style="color: #000000;">Order Management System</h1>

    <hr>
    <h2 style="text-align: center; color: #000000;">Save Orders</h2>
    <!--添加数据的页面--> <!--th:action 表单提交的url地址 @{} URL表达式 -->
    <form action="#" th:action="@{/saveOrders}" th:object="${orders}" method="POST">
        <!--订单ID的输入--> <!--th:field 用于指明要跳转的链接 *{}选择表达式,一般用于展示对象属性-->
        <input type="text" th:field="*{orderID}" placeholder="orderID" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">
        <!--订单时间的输入-->
        <input type="text" th:field="*{time}" placeholder="time" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">
        <!--订单收件人的输入-->
        <input type="text" th:field="*{consignee}" placeholder="consignee" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">
        <!--订单收件地址的输入-->
        <input type="text" th:field="*{addr}" placeholder="addr" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">
        <!--订单状态的输入-->
        <input type="text" th:field="*{status}" placeholder="status" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">

        <div style="display: flex; justify-content: center; align-items: center;">
            <button type="submit" class="btn btn-dark col-2">Save Orders</button>
        </div>
    </form>
    <hr>

    <div style="display: flex; color: #000000; justify-content: center; align-items: center;">
        <a th:href="@{/}" style="text-align: center;">Back to Orders List</a>
    </div>

</div>

</body>
</html>

效果:
在这里插入图片描述

6.3 update_orders.html部分

更新数据的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Order Management System</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

</head>
<body>
<div class="container my-2">
  <h1 class="text-center" style="color: #000000;">Order Management System</h1>

  <hr>
  <h2 style="text-align: center; color: #000000;">Update Order</h2>
  <form action="#" th:action="@{/saveOrders}" th:object="${orders}" method="POST">

    <!-- Add hidden form field to handle update -->
    <input type="hidden" th:field="*{id}"/>

    <input type="text" th:field="*{orderID}" placeholder="orderID" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">

    <input type="text" th:field="*{time}" placeholder="orderID" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">

    <input type="text" th:field="*{consignee}" placeholder="consignee" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">

    <input type="text" th:field="*{addr}" placeholder="addr" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">

    <input type="text" th:field="*{status}" placeholder="status" class="form-control mx-auto mb-4 col-4" style="border: 1px solid #000000">

    <div style="display: flex; justify-content: center; align-items: center;">
      <button type="submit"  class="btn btn-info col-2"> Update Orders</button>
    </div>
  </form>
  <hr>

  <div style="display: flex; color: #000000; justify-content: center; align-items: center;">
    <a th:href="@{/}" style="text-align: center;">Back to Orders List</a>
  </div>

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

效果:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值