实验七的实验内容二(期末) SpringBoot整合ssm项目,超详细分析

题目

某书店库存图书与售出图书如下表所示,当客户来购买图书时,书店会减少库存图书数量,并增加相应的售出图书数量。使用Spring声明事务控制来保证库存图书数量和售出图书数量的二者变化一致。
在这里插入图片描述

用SpringBoot整合实现上述实验内容,从底层数据库经过Repository、Service、Controller到客户端,完成一个完整的SpringBoot项目。

讲解

根据上面的表得知,该项目并不难实现(就3个字段,能难到什么程度)。先思考一下开发步骤

  1. 在数据库中创建表
  2. 创建项目并导入所需的包
  3. 编写实体类
  4. 编写mapper层代码
  5. 编写service层
  6. 编写controller层
  7. 编写客户端界面
  8. 测试
那现在我们边按步骤开发,边讲解需要注意的细节
1. 在数据库中创建表

我们将表名命名为book_store,创建表后插入原始记录

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for book_store
-- ----------------------------
DROP TABLE IF EXISTS `book_store`;
CREATE TABLE `book_store` (
  `id` int NOT NULL AUTO_INCREMENT,
  `status` varchar(10) NOT NULL COMMENT '状态',
  `num` int DEFAULT NULL COMMENT '数量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of book_store
-- ----------------------------
INSERT INTO `book_store` VALUES ('1', '库存', '100');
INSERT INTO `book_store` VALUES ('2', '售出', '50');

2. 创建项目并导入所需的包

开发工具选择的是Intellij IDEA,首先新建项目,选择Spring Initializer,命名为bookstore,Group为上层包名,注意选择自己的Java版本,点击next
在这里插入图片描述
我们需要用到下图所示的几个依赖包,点击finish,等待项目加载完成即可。
在这里插入图片描述
我们可以看到,pom中已经为我们导入依赖,默认为我们配置了一个application.properties,我们需要在其中完成数据源的配置

# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=root
3. 编写实体类

根据表中的字段,我们来创建一个对应的实体类

package person.yjx.bookstore.domain;

public class BookStore {
    private Integer id;
    private String status;
    private Integer num;

    @Override
    public String toString() {
        return "BookStore{" +
                "id=" + id +
                ", status='" + status + '\'' +
                ", num=" + num +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }
}

4. 编写mapper层代码

mapper层用mybatis来实现。我们需要一个查询所有记录的方法来读取售出与库存的数据,而售出本质上就是修改数据库的记录,所以我们还需要一个修改“num”记录的方法。需要注意的是,mybatis我们传入一个以上的参数时,使用的param1、param2……这种格式的。此外我们还需要一个根据id查询记录的方法,售出应该分为两个步骤,库存量减少,售出量增加。
如果你不知道这些方法有什么用,看下去你就明白了。

package person.yjx.bookstore.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;
import person.yjx.bookstore.domain.BookStore;

import java.util.List;

@Repository
@Mapper
public interface BookStoreMapper {

    @Select("select * from book_store")
    public List<BookStore> showAll();

//    注意mybatis多参传递的用法
    @Update("update book_store set num=#{param2} where id=#{param1}")
    public void update(int id, int num);

    @Select("select * from book_store where id=#{id}")
    public BookStore selectById(int id);

}

5. 编写service层

业务层有三个方法:一个是展示全部的记录,用于显示在客户端中库存与出售的数据。一个是添加库存的方法。一个是出库的方法。

package person.yjx.bookstore.service;

import person.yjx.bookstore.domain.BookStore;

import java.util.List;

public interface BookStoreService {
    public List<BookStore> showAll();

    public void input(int id, int add);

    public void sellOut(int id, int out);
}

在实现类中实现方法,重点讲解售出。在售出中,要完成售出数增加,库存数减少。首先查询目前的售出数,将目前的总售出数加上新售出的数量,再调用mapper层写到数据库中。再将库存数减少对应的数量。用@Transactional声明事务控制来保证库存图书数量和售出图书数量的二者变化一致。

package person.yjx.bookstore.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import person.yjx.bookstore.domain.BookStore;
import person.yjx.bookstore.mapper.BookStoreMapper;
import person.yjx.bookstore.service.BookStoreService;

import java.util.List;
@Service
public class BookStoreServiceImpl implements BookStoreService {

    @Autowired
    BookStoreMapper bookStoreMapper;

    @Override
    public List<BookStore> showAll() {
        return bookStoreMapper.showAll();
    }

    @Override
    public void input(int id, int add) {
        BookStore bookStore = bookStoreMapper.selectById(id);
        int num = add + bookStore.getNum();
        bookStoreMapper.update(id,num);
    }

    @Transactional
    @Override
    public void sellOut(int id, int out) {
        BookStore bookStore = bookStoreMapper.selectById(id);
        int num = bookStore.getNum() + out;
        bookStoreMapper.update(id,num);
//        int i = 1 / 0;
        input(1, -out );
    }
}

6. 编写controller层

注意看到第一个showAll方法的映射路径,这里写的是 / ,作用是项目启动时即访问showAll方法,将数据存放到model中,回传到first页面,即可完成页面数据的初始化。input与sellout方法在执行完毕后重定向到showAll中,为的是防止浏览器退回操作,导致表单重复提交,数据发生异常。

package person.yjx.bookstore.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import person.yjx.bookstore.domain.BookStore;
import person.yjx.bookstore.service.BookStoreService;

import java.util.List;

@Controller
public class BookStoreController {
    @Autowired
    BookStoreService bookStoreService;

    @RequestMapping("/")
    public String showAll(Model model) {
        List<BookStore> bookStores = bookStoreService.showAll();
        model.addAttribute("bookStores",bookStores);
        return "first";
    }

    @RequestMapping("/input")
    public String input(int id, int add){
        bookStoreService.input(id, add);
        return "redirect:/";
    }

    @RequestMapping("/sellOut")
    public String sellOut(int id, int out) {
        bookStoreService.sellOut(id,out);
        return "redirect:/";
    }

}

7. 编写客户端界面

前端的页面使用的是thymeleaf模板

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>bookstore</title>
</head>
<body>
<div>
    <div>
        <table>
            <tbody>
                <tr th:each="bookstore,stat:${bookStores}">
                    <td th:text="${bookstore.getStatus()}"></td>
                    <td th:text="${bookstore.getNum()}"></td>
                    <td th:if="${bookstore.getId()} eq 1">
                        <form action="/input" method="post">
                            <input type="number" required name="add">
                            <input type="hidden" name="id" value="1">
                            <input type="submit" value="入库">
                        </form>
                    </td>
                    <td th:if="${bookstore.getId()} eq 2">
                        <form action="/sellOut" method="post">
                            <input type="number" required name="out">
                            <input type="hidden" name="id" value="2">
                            <input type="submit" value="出售">
                        </form>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
</body>
</html>
8. 测试

启动页面
在这里插入图片描述
输入1
在这里插入图片描述
点击出售
在这里插入图片描述
能够同时完成售出数加一与库存数减一操作。

总结

该项目能完成题目要求实现功能,但是比较简陋,前端界面就随便一做而已的,可以优化。而且,没有使用正则表达式完成数据输入的控制,若输入的为负数时,程序不会出错,但是不符合现实逻辑,所以需要改进添加正则表达式限制前端输入的数据。

源码下载

需要源码的同学可以点击此处下载

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值