实现商品CRUD操作

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

准备工作

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

技术架构
采用典型的c/s架构进行实现,客户端我们基于浏览器进行实现,服务端采用tomacat,数据库使用mysql,具体应用层基于mvc分层架构实现

技术栈
客户端:html,css,js,bootstrap
服务端:spring,springboot,mybaties,thymeleaf
数据库:mysql,SQL
API整合
实现商品CRUD操作_第1张图片
初始化数据库
登录mysql mysql -uroot -proot
设置编码格式
set names utf8;
执行goods.sql文件

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

drop database if exists dbbrand;
create database dbbrand default character set utf8;
use dbbrand;
create table tb_brand(
     id bigint primary key auto_increment,
     name varchar(100) not null,
     remark text,
     createdTime datetime not null
)engine=InnoDB;
insert into tb_brand values (null,'联想','very good',now());
insert into tb_brand values (null,'小米','very good',now());
insert into tb_brand values (null,'美的','very good',now());
insert into tb_brand values (null,'九阳','very good',now());
insert into tb_brand values (null,'TCL','very good',now());
insert into tb_brand values (null,'创维','very good',now());
insert into tb_brand values (null,'华为','very good',now());

基于idea创建
创建module
项目配置文件
application.properties,添加如下内容:

#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

添加依赖


   
      org.springframework.boot
      spring-boot-starter-data-jdbc
   
   
      org.springframework.boot
      spring-boot-starter-groovy-templates
   
   
      org.springframework.boot
      spring-boot-starter-jersey
   
   
      org.springframework.boot
      spring-boot-starter-thymeleaf
   
   
      org.springframework.boot
      spring-boot-starter-web
   
   
      mysql
      mysql-connector-java
      runtime
   

启动类检查是否能正常启动

领域对象Pojo类定义设计及实现

第一步:定义Goods对象,用于封装从数据库查询到的商品信息。

package com.cy.pj.goods.pojo;
import java.util.Date;
public class Goods {
    private Integer 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映射获取所有商品信息。代码如下:
**动态代码最好用映射方法
简单的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_brand where name like concat('%',#{name},'%')and name!=null or name!=''")
      //这样太复杂,复杂用映射比较好
      List findGoods(String name);
}

映射与注解俩者取其一
映射代码

@Mapper
public interface GoodsDao {
 List findGoods(String name);
 }

在resources目录下创建mapper文件
在创建xml映射文件

 


  
 ```
第三步:进行测试

ackage 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 goodsList=goodsDao.findGoods(null);
      for(Goods g:goodsList){
          System.out.println(g);
      }
  }
}

测试结果问题分析

  • 数据库连不上,如图所示:

  • 连接数据库的url 配置问题,如图所示:

  • Sql映射重复定义问题,如图所示:

  • 空指针问题,如图所示:

  • SQL语法问题,如图所示:

业务逻辑对象
是对象负责模块的具体业务处理如:日志,权限等等
第一步:定义业务接口,添加品牌查询方法

import com.cy.pj.goods.pojo.Goods;
import java.util.List;
public interface GoodsService {
    List findBrannds(String name);
}

第二步:定义接口实现类

package com.cy.pj.goods.pojo;
import com.cy.pj.goods.Dao.GoodsDao;
import com.cy.pj.goods.Dao.GoodsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Service
public class GoodsImp implements GoodsService {
    private static final Logger log= LoggerFactory.getLogger(GoodsImp.class);
    @Autowired
 private GoodsDao goodsDao;
    @Override
 public List findBrannds(String name) {
        long t1=System.currentTimeMillis();
        List list=goodsDao.findGoods(name);
        long t2=System.currentTimeMillis();
        log.info("find->",t2-t1);
        return list;
    }
}

第三步:进行单元测试

package com.cy.pj;
import com.cy.pj.goods.Dao.GoodsService;
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 BrandTest {
    @Autowired
 private GoodsService goodsService;
    @Test
 void dou(){
      List list=goodsService.findGoods("小米");
System.out.println(list.size());
Assertions.assertEquals(1, list.size());//断言测试
System.out.println("OK");
list.forEach(brand->System.out.println());//jdk1.8lambda表达式
    }
}

Controller对象方法定义及实现

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

package com.cy.pj.goods;
import com.cy.pj.goods.one.GoodsService;
import com.cy.pj.goods.pojo.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
@Controller
public class CollerGoods {
    @Autowired
 private GoodsService goodsService;
 //@PathVariable用于修饰参数,告诉mvc,参数来的url
   @GetMapping(value = {"/goods/doFind","/goods/doFind/{name}"})
    public String doFind(@PathVariable(required = false) String name, Model model){
        List list=goodsService.findGoods(name);
        model.addAttribute("list", list);
        return "brand";
    }
}

测试:http://localhost/goods/doFind...

改造成:

package com.cy.pj.goods;
import com.cy.pj.goods.one.GoodsService;
import com.cy.pj.goods.pojo.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class CollerGoods {
    @Autowired
 private GoodsService goodsService;
    @GetMapping("/goods/doFind")
    public String doFind( String name, Model model){
        List list=goodsService.findGoods(name);
        model.addAttribute("list", list);
        return "brand";
    }
}

测试:http://localhost/goods/doFind

客户端向服务器提交数据,在服务器没有收到?
一点要看客户端提交数据的方式和服务端的请求方式
服务端向客户端响应数据时,假如客户端没有收到?
先检测服务端响应数据之前的数据是什么

brand.html:



    Good Thymes Virtual Grocery
    
    










id name remark createdTime operation
1 MySQL DBMS 2020/07/03 delete

项目启动及运行过程中BUG及问题分析

  • STS控制台“?”符号,如图所示:

  • 服务启动失败,如图所示:

  • 模板不存在错误,如图所示:

  • 日期格式不正确,如图所示:

  • 页面上${}内容错误,如图所示:

  • 页面日期格式不正确,如图所示:

  • 依赖注入失败,如图所示:

  • 空指针异常(NullPointerException),如图所示:

405异常表示客户端提交的请求方式与服务端可处理的请求不匹配

商品删除业务实现

业务描述

从商品库查询商品信息后,点击页面上删除超链接,基于id删除当前行记录

业务时序分析

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

Dao接口方法及映射定义

在GoodsDao接口中定义商品删除方法以及SQL映射

@Delete("delete from tb_brand where id=#{id}")
int findGoods02(Integer id);

brand.html添加删除

delete

按钮模式



function delectBy(id){
if(!confirm("确定删除吗")) return;
location.href="http://localhost/goods/delectBy/"+id;
}

1)${}为thymeleaf为中的EL表达式,用于从服务端model中获取数据
2)th:each为thymeleaf定义的自定义标签属性,用于迭代数据.
3)th:text为thymeleaf定义的自定义标签属性,用于设置文本内容.

Service接口方法定义及实现

在GoodsService接口中添加删除方法,代码如下:

int findGoods02(Integer id);

在GoodsService的实现类GoodsImp中添加deleteById方法实现。代码如下。

@Override
public int findGoods02(Integer id) {
    long t1=System.currentTimeMillis();
   int rows=goodsDao.findGoods02(id);
    long t2=System.currentTimeMillis();
    log.info("find02->{}",t2-t1);
    return rows;
}

在实现类中的添加doDeleteById方法,代码如下:

 @GetMapping("/goods/delectBy/{id}")
public String delectBy(@PathVariable Integer id,Model model){
   goodsService.findGoods02(id);
    List list=goodsService.findGoods(null);
    model.addAttribute("list", list);
   return "brand";
}

测试:正常运行就基本ok

@Test
void testwo(){
    int rows=goodsService.findGoods02(10);
 Assertions.assertNotEquals(-1, rows);
    System.out.println(rows);
}

项目启动及运行过程中的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;
    } 

写一个Good.html,来看成功是否
如下:




    
    Title


成功

Controller对象方法定义及实现

在GoodsController类中添加用于处理商品添加请求的方法,代码如下:

@RequestMapping("/goods/doAll")
public String doAll(Goods en){
    goodsService.saveGoods(en);
    return "Good";
}

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

@GetMapping("/goods/doGoodsAddUI")
public String doGoodsAddUI() {
    return "one";
}

Goods添加页面设计及实现

在templates的pages目录中添加one.html页面,代码如下








The Goods Add Page

  • name:
  • remark:

在brand.html页面中添加,超链接可以跳转到添加页面,关键代码如下:

添加商品


启动Tomcat服务器进行访问测试分析

第一步:启动web服务器,检测启动过程是否OK,假如没有问题进入下一步。
第二步:打开浏览器在地址里输入http://localhost/goods/doGood...),出现如下界面,如图所示:

第三步:在添加页面中填写表单,然后点击save按钮将表单数据提交到服务端,如图所示:

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

  • 客户端显示400异常,如图所示:

  • 保存时500异常,如图所示:

  • 数据库完整性约束异常,如图所示:

商品修改业务实现

业务描述

在商品列表页面,点击update选项,基于商品id查询当前行记录然后将其更新到goods-update页面,如图所示:

在update页面选中,修改商品信息,然后点击 update goods 将表单数据提交到服务端进行更新

业务时序分析

基于id查询商品信息的时序设计

Dao接口方法及映射定义

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

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

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

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

Service接口方法定义及实现

在GoodsService 中添加基于id查询商品信息和更新商品信息的方法,代码如下:

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

在brand.html页面中添加,超链接可以跳转到修改页面,关键代码如下:


在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查询商品信息的方法,代码如下:

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

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

 @GetMapping("/goods/doUpdate")
public String doUpdategoods(Goods goods){
    goodsService.updateGoods(goods);
    return "Good";
}

Goods修改页面设计及实现

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





Insert title here



   

The Goods Update Page

  • name:
  • remark:

启动Tomcat服务进行访问测试分析

启动tomcat服务,访问商品列表页面,如图所示:

在列表页面,点击update选项,进入更新页面

在更新页面更新表单数据,然后提交,进入列表页面查看更新结果,如图所示:

结束

你可能感兴趣的:(java)