关于springboot:07SpringBootMyBatisSpring技术整合实现商品模块的CRUD操作

40次阅读

共计 10266 个字符,预计需要花费 26 分钟才能阅读完成。

业务形容

基于 Spring,MyBatis,SpringBoot,Thymeleaf 技术实现商品模块的增删改查操作。

我的项目环境初始化

筹备工作

1. MySQL(5.7)
2. JDK (1.8)
3. Maven (3.6.3)
4. STS(4.7.1)

数据库初始化

关上 mysql 控制台, 而后按如下步骤执行 goods.sql 文件。
第一步: 登录 mysql。

mysql –uroot –proot

第二步: 设置控制台编码方式。

set names utf8;

第三步: 执行 goods.sql 文件(切记不要关上文件复制到 mysql 客户端运行)。

source d:/goods.sql

其中 goods.sql 文件内容如下:

drop database if exists dbgoods;
create database dbgoods default character set utf8;
use dbgoods;
create table tb_goods(
     id bigint primary key auto_increment,
     name varchar(100) not null,
     remark text,
     createdTime datetime not null
)engine=InnoDB;
insert into tb_goods values (null,'java','very good',now());
insert into tb_goods values (null,'mysql','RDBMS',now());
insert into tb_goods values (null,'Oracle','RDBMS',now());
insert into tb_goods values (null,'java','very good',now());
insert into tb_goods values (null,'mysql','RDBMS',now());
insert into tb_goods values (null,'Oracle','RDBMS',now());
insert into tb_goods values (null,'java','very good',now());

创立我的项目并增加依赖

基于 STS 创立

第一步:基于 start.spring.io 创立我的项目并设置根本信息
第二步:创立我的项目时指定我的项目外围依赖
第三步:我的项目创立当前剖析其构造

基于 IDEA 创立

第一步:基于 start.spring.io 创立我的项目并设置根本信息
第二步:创立我的项目 module 时指定我的项目外围依赖
第三步:我的项目 modul 创立当前剖析其构造

我的项目配置文件内容初始化

#server
server.port=80
#server.servlet.context-path=/
#spring datasource
spring.datasource.url=jdbc:mysql:///dbgoods?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

#spring mybatis
mybatis.mapper-locations=classpath:/mapper/*/*.xml

#spring logging
logging.level.com.cy=debug

#spring thymeleaf
spring.thymeleaf.prefix=classpath:/templates/pages/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false

我的项目 API 架构设计

其 API 架构设计,如图所示:

商品查问业务实现

业务形容

从商品库查问商品信息,并将商品信息出现在页面上,如图所示:

业务时序剖析

查问所有商品信息,其业务时序剖析,如图所示:

Pojo 类定义

定义 Goods 对象,用于封装从数据库查问到的商品信息。

package com.cy.pj.goods.pojo;
import java.util.Date;
public class Goods {
    private Long id;//id bigint primary key auto_increment
    private String name;//name varchar(100) not null
    private String remark;//remark text
    private Date createdTime;//createdTime datetime
    public Long getId() {return id;}
    public void setId(Long id) {this.id = id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public String getRemark() {return remark;}
    public void setRemark(String remark) {this.remark = remark;}
    public Date getCreatedTime() {return createdTime;}
    public void setCreatedTime(Date createdTime) {this.createdTime = createdTime;}
    @Override
    public String toString() {
        return "Goods [id=" + id + ", name=" + name + ",   
        remark="+ remark +", createdTime="+ createdTime +"]";
    }
}

Dao 接口办法及映射定义

在 GoodsDao 接口中定义商品查询方法以及 SQL 映射,基于此办法及 SQL 映射获取所有商品信息。代码如下:

package com.cy.pj.goods.dao;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import com.cy.pj.goods.pojo.Goods;

@Mapper
public interface GoodsDao {@Select("select * from tb_goods")
      List<Goods> findGoods();}

编写单元测试类进行测试剖析:

package com.cy.pj.goods.dao;
import com.cy.pj.goods.pojo.Goods;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class GoodsDaoTests {
    @Autowired
 private GoodsDao goodsDao;
    @Test
 void testFindGoods(){List<Goods> goodsList=goodsDao.findGoods();
        for(Goods g:goodsList){System.out.println(g);
        }
    }
}

测试后果问题剖析

  • 数据库连不上,如图所示:
  • 连贯数据库的 url 配置问题, 如图所示:
  • Sql 映射反复定义问题, 如图所示:
  • 空指针问题, 如图所示:
  • SQL 语法问题,如图所示:

Service 接口办法定义及实现

GoodsService 接口及商品查询方法定义

package com.cy.pj.goods.service;
import java.util.List;
import com.cy.pj.goods.pojo.Goods;
public interface GoodsService {List<Goods> findGoods();
}

GoodsService 接口实现类 GoodsServiceImpl 定义及办法实现

package com.cy.pj.goods.service;
import java.util.List;
import com.cy.pj.goods.pojo.Goods;
@Service
public class GoodsServiceImpl implements GoodsService {
     @Autowired
     private GoodsDao goodsDao;
     @Override
     public List<Goods> findGoods(){return goodsDao.findGoods();
     }
}

编写单元测试类进行测试剖析

package com.cy.pj.goods.service;
import com.cy.pj.goods.pojo.Goods;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class GoodsServiceTests {
    @Autowired
 private GoodsService goodsService;
    @Test
 void testFindGoods(){List<Goods> goodsList=goodsService.findGoods();
        // 断言测试法(单元测试中罕用的一种形式)Assertions.assertEquals(true, goodsList.size()>0);
    }
}

测试后果问题剖析

  • 依赖注入问题, 如图所示:

Controller 对象办法定义及实现

定义 GoodsController 类,并增加 doGoodsUI 办法,增加查问商品信息代码,并将查问到的商品信息存储到 model,并返回 goods 页面。

package com.cy.pj.goods.controller;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import com.cy.pj.goods.pojo.Goods;
import com.cy.pj.goods.service.GoodsService;
@Controller //@Service,@Component
@RequestMapping("/goods/")
public class GoodsController {
    //has a+di
    @Autowired
    private GoodsService goodsService;
    @RequestMapping("doGoodsUI")
    public String doGoodsUI(Model model) {
         // 调用业务层办法获取商品信息
         List<Goods> list= goodsService.findGoods();
         // 将数据存储到申请作用域
         model.addAttribute("list", list);
         return "goods";//viewname
    }
    
}

Goods 商品列表页面设计及实现

在 templates/pages 目录中增加 goods.html 页面,并在 body 中增加 html 元素,在运行外部应用 thymeleaf 标签属性获取数据,代码如下:

<table width="50%">
        <thead>
           <th>id</th>
           <th>name</th>
           <th>remark</th>
           <th>createdTime</th>
           <th>operation</th>
        </thead>
        <tbody>
           <tr th:each="g:${list}">
             <td th:text="${g.id}">1</td>
             <td th:text="${g.name}">MySQL</td>
             <td th:text="${g.remark}">DBMS</td>
             <td th:text="${#dates.format(g.createdTime,'yyyy/MM/dd HH:mm')}">2020/07/03</td>
             <td><a>delete</a></td>
           </tr>
        </tbody>
  </table>

thymeleaf 是一种模板引擎,此引擎以 html 为模板,能够增加自定义标签属性,能够将服务端 model 中数据填充在页面上,而后实现与用于交互。其官网为 thymeleaf.org

Goods 页面上数据出现剖析:

启动 Tomcat 进行拜访测试剖析

首先,启动 tomcat,而后在关上浏览器,在地址栏输出拜访地址,获取服务端数据并进行出现,如图所示:

我的项目启动及运行过程中 BUG 及问题剖析

  • STS 控制台“?”符号,如图所示:
  • 服务启动失败,如图所示:
  • 模板不存在谬误,如图所示:
  • 日期格局不正确,如图所示:
  • 页面上 ${}内容谬误,如图所示:
  • 页面日期格局不正确,如图所示:
  • 依赖注入失败,如图所示:
  • 空指针异样(NullPointerException), 如图所示:

商品删除业务实现

业务形容

从商品库查问商品信息后,点击页面上删除超链接,基于 id 删除以后行记录,如图所示:

业务时序剖析

在商品出现页面,用户执行删除操作,其删除时序如图所示:

Dao 接口办法及映射定义

在 GoodsDao 接口中定义商品删除办法以及 SQL 映射,代码如下:

 @Delete("delete from tb_goods where id=#{id}")

 int deleteById(Integer id);

Service 接口办法定义及实现

在 GoodsService 接口中增加删除办法,代码如下:

int deleteById(Integer id);

在 GoodsService 的实现类 GoodsServiceImpl 中增加 deleteById 办法实现。代码如下。

@Override
    public int deleteById(Integer id) {long t1=System.currentTimeMillis();
        int rows=goodsDao.deleteById(id);
        long t2=System.currentTimeMillis();
        System.out.println("execute time:"+(t2-t1));
        return rows;
    }

Controller 对象办法定义及实现

在 GoodsController 中的增加 doDeleteById 办法,代码如下:

 @RequestMapping("doDeleteById/{id}")
    public String doDeleteById(@PathVariable Integer id){goodsService.deleteById(id);
        return "redirect:/goods/doGoodsUI";
    }

阐明:Restful 格调为一种软件架构编码格调, 定义了一种 url 的格局,其 url 语法为 /a/b/{c}/{d}, 在这样的语法结构中 {} 为一个变量表达式。如果咱们心愿在办法参数中获取 rest url 中变量表达式的值, 能够应用 @PathVariable 注解对参数进行形容。

Goods 页面上删除超链接定义

在 goods.html 页面中增加删除超链接,如图所示:
Thymeleaf 官网 th:href 利用阐明,如图所示:
删除操作中,客户端与服务端代码关联阐明,如图所示:

启动 tomcat 服务器进行拜访测试剖析

首先,启动 tomcat,而后在关上浏览器,在地址栏输出拜访地址,获取服务端数据并进行出现,接下来点击页面上的删除按钮,如图所示:
删除胜利当前,的页面如图所示:

我的项目启动及运行过程中的 Bug 及问题剖析

  • SQL 映射元素定义问题,如图所示:
  • 客户端申请参数与服务端参数不匹配,如图所示:

商品增加业务实现

业务形容

在 Goods 列表页面,增加增加按钮,进行增加页面,而后在增加页面输出商品相干信息,而后保留到数据库,如图所示:
商品增加页面,设计如图所示:

业务时序剖析

在商品增加页面,输出商品信息,而后提交到服务端进行保留,其时序剖析如图所示:

Dao 接口办法及映射定义

在 GoodsDao 中增加用于保留商品信息的接口办法以及 SQL 映射,代码如下:

@Insert("insert into tb_goods(name,remark,createdTime) 
values (#{name},#{remark},now())")
int insertObject(Goods entity);

阐明:当 SQL 语句比较复杂时,也能够将 SQL 定义到映射文件(xml 文件)中。

Service 接口办法定义及实现

在 GoodsService 接口中增加业务办法,用于实现商品信息增加,代码如下:

int saveGoods(Goods entity);

在 GoodsSerivceImpl 类中增加接口办法实现,代码如下:

 @Override
    public int saveGoods(Goods entity) {int rows=goodsDao.insertObject(entity);
        return rows;
    }

Controller 对象办法定义及实现

在 GoodsController 类中增加用于解决商品增加申请的办法,代码如下:

@RequestMapping("doSaveGoods")
public String doSaveGoods(Goods entity) {goodsService.saveGoods(entity);
        return "redirect:/goods/doGoodsUI";
}

在 GoodsController 类中增加用于返回商品增加页面的办法,代码如下:

 @RequestMapping("doGoodsAddUI")
    public String doGoodsAddUI() {return "goods-add";}

Goods 增加页面设计及实现

在 templates 的 pages 目录中增加 goods-add.html 页面,代码如下

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css"> ul li {list-style-type: none;} </style>
</head>
<body>
<h1>The Goods Add Page</h1>
<form th:action="@{/goods/doSaveGoods}" method="post">
   <ul>
      <li>name:
      <li><input type="text" name="name">
      <li>remark:
      <li><textarea rows="5" cols="50" name="remark"></textarea>
      <li><input type="submit" value="Save">
   </ul>
</form>
</body>
</html>

在 goods.html 页面中增加,超链接能够跳转到增加页面,要害代码如下:

<a th:href="@{/goods/doGoodsAddUI}"> 增加商品 </a>

启动 Tomcat 服务器进行拜访测试剖析

第一步:启动 web 服务器,检测启动过程是否 OK,如果没有问题进入下一步。
第二步:关上浏览器在地址里输出 http://localhost/goods/doGood…),呈现如下界面,如图所示:
第三步:在增加页面中填写表单,而后点击 save 按钮将表单数据提交到服务端,如图所示:
第四步:增加页面中表单数据提交过程剖析,如图所示:

我的项目启动及运行过程中的 Bug 及问题剖析

  • 客户端显示 400 异样,如图所示:
  • 保留时 500 异样,如图所示:
  • 数据库完整性束缚异样,如图所示:

商品批改业务实现

业务形容

在商品列表页面, 点击 update 选项, 基于商品 id 查问以后行记录而后将其更新到 goods-update 页面, 如图所示:
在 update 页面选中, 批改商品信息, 而后点击 update goods 将表单数据提交到服务端进行更新

业务时序剖析

基于 id 查问商品信息的时序设计
将 goods-update 页面中的数据提交到服务端进行更新的时序设计

Dao 接口办法及映射定义

在 GoodsDao 中增加基于 id 查问商品信息的办法及 SQL 映射, 代码如下:

@Select("select * from tb_goods where id=#{id}")
Goods findById(Integer id);

在 GoodsDao 中增加基于 id 执行 Goods 商品更新的办法及 SQL 映射, 代码如下:

 @Update("update tb_goods set name=#{name},remark=#{remark} where id=#{id}")
 int updateGoods(Goods goods);

Service 接口办法定义及实现

在 GoodsService 中增加基于 id 查问商品信息和更新商品信息的办法, 代码如下:

Goods findById(Integer id);
int updateGoods(Goods goods);

在 GoodsServiceImpl 中基于 id 查问商品信息和更新商品信息的办法, 代码如下:

 @Override
    public Goods findById(Integer id) {
        //.....
        return goodsDao.findById(id);
    }
 @Override
    public int updateGoods(Goods goods) {return goodsDao.updateGoods(goods);
    }

Controller 对象办法定义及实现

在 GoodsController 中增加基于 id 查问商品信息的办法, 代码如下:

 @RequestMapping("doFindById/{id}")
    public String doFindById(@PathVariable Integer id,Model model) {Goods goods=goodsService.findById(id);
        model.addAttribute("goods",goods);
        return "goods-update";
    }

在 GoodsController 中增加更新商品信息的办法, 代码如下:

 @RequestMapping("doUpdateGoods")
    public String doUpdateGoods(Goods goods) {goodsService.updateGoods(goods);
        return "redirect:/goods/doGoodsUI";
    }

Goods 批改页面设计及实现

在 templates 目录中增加 goods-update.html 页面, 代码设计如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css"> ul li {list-style-type: none} </style>
</head>
<body>
   <h1>The Goods Update Page</h1>
   <form th:action="@{/goods/doUpdateGoods}" method="post">
      <input type="hidden" name="id" th:value="${goods.id}">
      <ul>
        <li>name:
        <li><input type="text" name="name" th:value="${goods.name}">
        <li>remark:
        <li><textarea rows="3" cols="30" name="remark" th:text="${goods.remark}"></textarea>
        <li><input type="submit" value="Update Goods">
       </ul>
   </form>
</body>
</html>

启动 Tomcat 服务进行拜访测试剖析

启动 tomcat 服务, 拜访商品列表页面, 如图所示:
在列表页面, 点击 update 选项, 进入更新页面
在更新页面更新表单数据, 而后提交, 进入列表页面查看更新后果, 如图所示:

我的项目启动及运行过程中的 BUG 及问题剖析

  • 页面设计剖析, 如图所示:
  • 页面源码剖析, 如图所示:

总结(Summary)

本大节重点解说了 SpringBoot 工程下 MyBatis,SpringMVC,Thymeleaf 技术的综合利用,重点了解其业务实现过程以及问题的解决过程。

正文完
 0