javaee之黑马乐优商城4

news2024/11/26 13:40:10

商品规格与数据结构

 

 下面来说一下数据库的设计与分析

 其实对于spu这张表来说,大体设计还是比较好设计的

 看一下下面这张图是一个产品的规格参数

上面主体就是一个规格参数,基本信息又是一个规格参数

这里就是涉及到了一个商品的具体信息,sku就是一个具体带有了规格参数的商品

 先不管上面表设计的具体细节,先来看下面一张图

那我们在来分析几张表与表之间的关系

 下面对上面的关系进行拓展,先来看下面几个页面

上面这张图就是我们要用于搜索的规格参数,就是哪些规格参数要拿上来作为参数条件

上面这张图就是讲这些规格参数,都是从什么类型的表上获取数据的方式

有了上面的信息,下面我去看一下上面这些表在数据中的具体信息

先来看分类表

 这张表创建了一个相关的分类信息,这张表重点关注parent_id与is_parent这两个字段

下面用一张图来解释这个目录结构

下面在讲解一下sort这个排序指数,越小越靠前

下面我们说一下一般在数据库里面我们都怎样进行查询

1.比如我们查出所有的顶级父类,也就是parent_id = 0 的所有分类

2.下面我们做一个查询是通过某一个父子类,去查找到它下面的所有直接的直接子类,比如下面这样查询

 比如点击图书、音像、电子书刊就能找到电子书刊和音像这两个直接子类

首先分析一下,父类与它的直接子类关联的字段就是parent_id,也就是在一棵树中,同级之间的兄弟子类的parent_id都是一样的,于是我们可以进行下面的sql语句查询

如果还要继续深入的往子类与子类的查找,还是查找当前结点的parent_id,然后根据这个parent_id来查找它的直接子类

分类表看了之后,我们来看参数数组表

这个表我们还没有被创建出来,在创建之前,我们先来看一下这张表与tb_category表之间的关系

先用习惯思维考虑一下,一个分类下面肯定有多个参数组的信息,

我们进入淘宝,看一下手机-》华为手机拥有的规格参数信息

上面一个手机分类下面就有很多不同的参数组 ,比如说有基本信息组,有屏幕组,有网络组

下面我们去看一下tb_spec_grop这张表

我们在数据库中还没有构建出来,我们先去把这张表给构建出来

然后现在我们向这个表里面插入一些数据

类似于如下

对于插入做一个简单的数据分析 

这个时候我们又要来说到另外一张表

这张表就是规格参数组表的每一个组对应的具体的规格属性,这个可以这样来理解,就是参数组表里面存放的是表头,具体的规格参数名是放在这个规格参数表名里面,这张表的名字是tb_spec_param(明显与参数数组表是一个一(tb_spec_group)对多(tb_spec_param)的关系)

下面我们把这张具体的参数表给创建出来

上面简单分析一下重点字段的得来

上面cid是因为一个分类下面会从sku里面或者spu里面抽取很多参数属性来作为搜索部分的条件

比如下面

其中gid的说明:参数组与参数表是一个1对多的关系,在多的一方肯定引入参数组的id,然后两者才能相互关联

其中generic字段的说明:是否是spu通用属性,意思就是这个属性是不是放到大家都能查找到的部分,也就是规格参数里面共同的部分,比如主体信息,这个字段的重要性在于如果它是ture,也就是通用属性,我们要去spu里面参数值,如果不是通用部分,我们要去sku里面找值

上面就是创建了这张表,下面我们去插入这张表的具体数据

类似于下面这些值

下面我们可以去看一下这张表里面保存的数据信息

下面我们说一下规格参数组页面分析

这里我们要实现点击一个分类之后,他会拿出一个参数组,同时我们还可以拿到这个参数组对应的参数列表

情况如下

其实最后点击啊落到的位置就是一个分类树你下面非父结点的位置,他下面才是保存真正的商品,也就是一个分类树下面,这个节点is_parent = 0 ,他下面就是保存了具体的商品

下面继续分析这个页面布局

上面这是初始页面

 我们如果一直点,然后点到最后,他会提示

 因为规格是与商品分类绑定的,因此首先会展示商品分类树,提示你要选择的商品分类,才能看到规格参数模板,下面看一下页面实现

这个页面我们简单去了解一下前端

 下面就是右侧部分,我们规格参数展示的效果

下面就是展示具体的参数数据

 下面这些内容都可以大概的看一看

 

 下面的规格参数组和参数信息都是我们自己定义的组件,去找一下这个组件

找到页面中的点击事件,这个就是我们要清楚页面是怎么发的

在获得分类之后我们有一个点击事件

上面就是handleClick这个点击事件

这个点击事件,我们就可以去获取到这个节点一些信息,并且给它封装到了currentNode这个对象里面

 

 下面我们具体展示规格参数组的组件SpecGroup.vue

上面就会发送一个请求,根据分类来找到参数组

有了这样一个接口之后,我们就可以去写页面

请求方式:get 请求参数是一个cid,请求路径是/spec/groups 返回的是什么?

分析一下这里是一个表

 也没有进行分页,所以大概率情况下是返回一个List集合,里面保存的是一个参数规格组的对象

下面就可以去实现这部分的代码

 下面看tb_spec_group这个表关联的类SpecGroup

package com.leyou.item.pojo;

import javax.persistence.*;

@Table(name = "tb_spec_group")
public class SpecGroup {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;//自己的主键id

    private Long cid;//里面维护一个分类id,利用这个id可以找到参数组头

    //我们需要查询一个分组下面的规格参数
    //这个spec_group表与spec_param表是一个1对多的关系
    //所以我们放一个Spec_param的集合对象
    //这个是1的一方,引入集合个多的一方
    @Transient
    private List<SpecParam> params;
}

下面去做tb_spec_param这张表关联的类SpecParam

package com.leyou.item.pojo;

import javax.persistence.*;

@Table(name="tb_spec_param")
public class SpecParam {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Long cid;
    private Long groupId;
    private String name;
    @Column(name = "`numeric`")
    private Boolean numeric;
    private String unit;
    private Boolean generic;
    private Boolean searching;
    private String segments;

    public Long getId() {
        return id;
    }

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

    public Long getCid() {
        return cid;
    }

    public void setCid(Long cid) {
        this.cid = cid;
    }

    public Long getGroupId() {
        return groupId;
    }

    public void setGroupId(Long groupId) {
        this.groupId = groupId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Boolean getNumeric() {
        return numeric;
    }

    public void setNumeric(Boolean numeric) {
        this.numeric = numeric;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public Boolean getGeneric() {
        return generic;
    }

    public void setGeneric(Boolean generic) {
        this.generic = generic;
    }

    public Boolean getSearching() {
        return searching;
    }

    public void setSearching(Boolean searching) {
        this.searching = searching;
    }

    public String getSegments() {
        return segments;
    }

    public void setSegments(String segments) {
        this.segments = segments;
    }
}

这里有个@Column注解的作用是区分数据库字段这里加上``反引号,是因为numeric这个字段是mysql里面的关键字

 下面我们要去编写我们的业务

先去完成mapper这个接口

package com.leyou.item.mapper;

import com.leyou.item.pojo.SpecGroup;
import tk.mybatis.mapper.common.Mapper;

public interface SpecGroupMapper extends Mapper<SpecGroup> {
}

上面继承了通用mapper,下面我们去写Controller,写Controller之前,我们先分析一下下面需要的东西,在页面的ajax请求中可以看出

在来说一下这里的Mapper,这里是SpecGroupMapper,为什么不是SpecificationMapper,因为一张表对应一个Mapper,对于规格参数来说,有两个这样类,一个是SpecGroup,一个是SpecParam

      SpecificationController.java

         

package com.leyou.item.web;

import com.leyou.item.pojo.SpecGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("spec")
public class SpecificationController {
    
    @Autowired
    private SpecificationService specificationService;

    @GetMapping("groups/{cid}")
    public ResponseEntity<List<SpecGroup>> queryGroupsByCid(@PathVariable("cid") Long cid) {
        List<SpecGroup> groups = this.specificationService.queryGroupsByCid(cid);
        if(CollectionUtils.isEmpty(groups)) {
            //如果为空
            //直接构建一个404的状态码
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(groups);
        //另外一种写法
       // return ResponseEntity.status(HttpStatus.OK).body(groups);
    }
}

 上面有一个工具类CollectionUtils,这个是spring给我们提供的来处理集合

 下面我们又要去完成service里面的方法

package com.leyou.item.service;

import com.leyou.item.mapper.SpecGroupMapper;
import com.leyou.item.pojo.SpecGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SpecificationService {

    @Autowired
    private SpecGroupMapper groupMapper;

    public List<SpecGroup> queryGroupsByCid(Long cid) {
        //利用通用mapper中的select完成查询工作,需要传入一个查询的实体类
        SpecGroup specGroup = new SpecGroup();
        specGroup.setCid(cid);
        return this.groupMapper.select(specGroup);
    }


}

下面我们进行一个页面访问测试

重新启动一下ly-item这个微服务

组名没有被查询到

检查了一下代码,发现

 

根本没有名字给我们返回,原来在下面我忘了加上name这个属性字段

 加上重启微服务,同时要注意给这个字段加上set与get方法

上面就完成了参数组的查询操作 

下面要去做规格参数的查询

 

我们可不可以直接找到这个接口

 这个接口路径已经被拿到了

按照惯例我们先去分析一下前端页面

这里是点击规格组的时候,就会切换到规格参数的一个显示,那么我们判定肯定是在规格组中绑定了点击事件

下面就会去触发这个方法

这个方法作用是

 

 回到我们的父组件,也就是Specification.vue这个组件

<spec-group :cid="currentNode.id" v-show="showGroup" @select="selectGroup"/>

事件处理函数

 下面分析一下页面查询规格参数

 下面我们去实现代码

 先来写上Mapper这个类

然后我们来写我们的Controller类

这个都是规格参数相关的操作,所以用一个SpecificationController类

把请求路径贴过来

 

 方式get,路径是/spec/params

参数是:gid,也就是分组id

返回结果:该分组下的规格参数集合List<SpecParam>

对一这个返回结果来多说一句

 一个分类下面的的参数组里面,每一个标题参数对应很多子类参数信息

上面这个主体里面,可能会有多条的记录信息,也就是有多个SpecParam对象

下面我们去完成代码

还是先去写我们的Mapper

 再去写我们的service层SpecificationService,这个service还是用之前的SpecificationService,只不过这次使用的Mapper是SpecParamMapper paramMapper

package com.leyou.item.service;

import com.leyou.item.mapper.SpecGroupMapper;
import com.leyou.item.mapper.SpecParamMapper;
import com.leyou.item.pojo.SpecGroup;
import com.leyou.item.pojo.SpecParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SpecificationService {

    @Autowired
    private SpecGroupMapper groupMapper;

    @Autowired
    private SpecParamMapper paramMapper;

    public List<SpecGroup> queryGroupsByCid(Long cid) {
        //利用通用mapper中的select完成查询工作,需要传入一个查询的实体类
        SpecGroup specGroup = new SpecGroup();
        specGroup.setCid(cid);
        return this.groupMapper.select(specGroup);
    }

    //之类就是通过参数组的gid来查询参数
    //这里考虑用通用Mapper的select,内部传入一个要返回的集合对象
    public List<SpecParam> queryParams(Long gid) {
        SpecParam param = new SpecParam();
        param.setGroupId(gid);
        return paramMapper.select(param);
    }


}

下面再去写我们的控制层面的代码

它的请求路径我们可以再去看一下

 返回的结果就是一个存放很多记录对象的集合,List<SpecParam>

package com.leyou.item.web;

import com.leyou.item.pojo.SpecGroup;
import com.leyou.item.pojo.SpecParam;
import com.leyou.item.service.SpecificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("spec")
public class SpecificationController {
    
    @Autowired
    private SpecificationService specificationService;

    @GetMapping("groups/{cid}")
    public ResponseEntity<List<SpecGroup>> queryGroupsByCid(@PathVariable("cid") Long cid) {
        List<SpecGroup> groups = this.specificationService.queryGroupsByCid(cid);
        if(CollectionUtils.isEmpty(groups)) {
            //如果为空
            //直接构建一个404的状态码
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(groups);
        //另外一种写法
       // return ResponseEntity.status(HttpStatus.OK).body(groups);
    }

    //根据参数组的gid查询规格参数
    public ResponseEntity<List<SpecParam>> queryParams(@RequestParam("gid")Long gid) {
       List<SpecParam> params = specificationService.queryParams(gid);
       //对于集合我们通常要做一些安全性检查的判定
        if(CollectionUtils.isEmpty(params)) {
            return ResponseEntity.notFound().build();//直接构建一个404的返回状态码
        }
        return ResponseEntity.ok(params);
    }

}

下面重启商品微服务模块,测试

注意把控制器这里的注解加上

测试一下 ,我们点击了主体这个参数组名,下面就会有很多条记录对象

 

 好了,先写到这,祝大家早安午安晚安。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1023674.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在时代的浪潮中实在前行!实在智能与浪潮通软全面开启战略合作

“新”潮涌动&#xff0c;浪花朵朵。近日&#xff0c;杭州实在智能科技有限公司与浪潮通用软件有限公司签署战略合作协议。双方将加快科研创新&#xff0c;扩大合作领域&#xff0c;共同开拓数智化市场&#xff0c;携手共赢。 浪潮通软平台软件与技术研究院总经理周祥国、实在智…

游戏使用脚本配置HTTP

在游戏世界中&#xff0c;使用脚本工具帮助优化游戏体验已经成为一种普遍现象。但是&#xff0c;是否需要结合代理IP来使用游戏脚本呢&#xff1f;本文将探讨游戏使用脚本时是否需要代理IP的利弊&#xff0c;并分享合规使用脚本的方法。 1. 提高账号安全性&#xff1a; - 通过…

知识图谱的搭建

知识图谱搭建最重要的核心在于对业务的理解以及对知识图谱本身的设计&#xff0c;这就类似于对于一个业务系统&#xff0c;数据库表的设计是至关重要的&#xff0c;而这种设计师根据业务及未来场景的变化预估不断探索得出的。 一个完整的知识图谱的构建包含以下几个步骤&#…

Spring 中的Aware接口有什么作用

文章目录 0.前言1.什么是Aware接口2.Aware接口的设计目的3.详解3.1. ApplicationContextAware我们举个例子来说明 3.2. BeanFactoryAware3.3. BeanNameAware3.4. ServletContextAware3.5. MessageSourceAware3.6. ResourceLoaderAware 4.参考文档 0.前言 背景&#xff1a; 最近…

Centos7完全离线环境安装Nvidia Tesla A100 40G显卡驱动(含CUDA Toolkit)和Anaconda3虚拟环境

公司一台完全离线环境的服务器刚装了Nvidia Tesla A100 40G显卡&#xff0c;自己摸索着将显卡驱动在完全离线环境下安装成功&#xff0c;这里记录一下。 一、下载Centos7适配的Nvidia Tesla A100 40G显卡驱动 在Nvidia官网下载Centos7适配的显卡驱动&#xff0c;CUDA Toolkit…

idea(第一次)启动项目,端口变成了8080

先上配置 server:port: 9569 spring:profiles:active: dev 该排查的问题也都没问题&#xff0c;重启idea也试过了&#xff0c;还是8080 解决办法&#xff1a;点击右侧的maven ,左上角的重新导入 reimport all maven projects 我又没有改动pom文件&#xff0c;居然还要点这…

玩机教程:阿里云无影云电脑怎么使用?

阿里云无影云电脑即无影云桌面&#xff0c;云电脑如何使用&#xff1f;云电脑购买后没有用户名和密码&#xff0c;先创建用户设置密码&#xff0c;才可以登录连接到云桌面。云桌面想要访问公网还需要开通互联网访问功能。阿里云百科来详细说下阿里云无影云电脑从购买、创建用户…

Android 13.0 SystemUI下拉状态栏背景增加高斯模糊背景

1.概述 在13.0的产品开发中,发现现在很多产品都是高斯模糊背景的,这种高斯模糊背景看起来效果很不错,产品开发需要SystemUI下拉状态栏背景也是高斯模糊背景,所以就要来实现下拉状态栏高斯模糊背景 2.SystemUI 下拉状态栏背景增加高斯模糊背景核心类 frameworks/base/pack…

python后端和前端通过websocket通讯发消息最小案例,十分钟看懂

前端和后端通过websocket实现发送消息案例&#xff0c;用于理解websocket&#xff0c;服务端可以主动给客户端发送消息&#xff0c;而且是长连接&#xff0c;比http效率高&#xff0c;因为http要不断地创建和销毁socket实例&#xff0c;导致压力很大。websocket一次创建&#x…

自定义类型:结构体----初学者笔记

目录 1. 结构体类型的声明 1.1 结构体类型的简单介绍和声明 1.1.1 结构的声明 1.1.2 特殊的声明 1.1.3 结构的自引用 2. 结构体变量的创建和初始化 3. 结构成员访问操作符 4. 结构体内存对⻬ 4.1 对齐规则 4.2 练习 4.2.1 练习1 4.2.2 练习2 4.3 为什么存在内存对…

知名IT网站博客园陷入绝境

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 博客园陷入生死存亡的绝境。 5月份知名IT开发者网站发布文章称“博客园网站遇到困难了&#xff1a;寻求捐助”&#xff0c;并开通了捐助渠道。4个月过去了&#xff0c;好像效果并不明显&#xff…

婚庆行业类软文怎么写?媒介盒子无偿分享

随着我国经济发展以及对婚礼品质要求的提升&#xff0c;结婚相关的市场发展愈发强劲&#xff0c;由于互联网发展的快速性&#xff0c;大部分新人选择通过网络获取结婚服务信息&#xff0c;所以线上成为婚庆公司的主要获客渠道。而软文营销就是婚庆公司提升品牌形象的主要方式&a…

AI写作工具,智能ai写作工具

在信息化时代&#xff0c;内容创作已经成为了许多行业的核心。从营销广告到新闻报道&#xff0c;从博客文章到学术论文&#xff0c;人们需要不断地产生高质量的文字内容。创作是一项耗时耗力的工作&#xff0c;需要丰富的知识和创造性思维。 AI写作工具&#xff0c;是一类基于人…

docker容器技术实战-3

08 docker 原生网络 原生网络&#xff1a;桥接模式 &#xff1a;生成虚拟网络对 host模式&#xff1a;容器和宿主机共享同一网络栈&#xff0c;不会新建虚拟网卡 none禁用网络&#xff1a;只用回环接口 自定义接口&#xff1a;内嵌dns解析 不同网络之间是被隔离的,默认不能通…

【C++】map与set的封装

文章目录 前言正文1. 类型的泛化2.仿函数3.迭代器3.1正向迭代器3.1.1 3.1.2 - -3.1.3 *3.1.4 ->3.1.5 !完整版代码 4.[]&#xff08;map&#xff09; 框架1.红黑树2.set3.map 总结 前言 在学习了红黑树之后&#xff0c;我们便可以尝试初步的在红黑树的基础上封装出map与set&…

Python日志处理器,同时打印到控制台和保存到文件中,并保证格式一致

使用logging模块的时候&#xff0c;默认是输出到控制台的&#xff0c;当然也可以配置输出到文件中&#xff0c;但是当你配置了文件后&#xff0c;控制台的输出就消失了&#xff0c;所以&#xff0c;需要一个策略即能保存到文件中&#xff0c;又能输出到控制台中。 下面是我做的…

ORB-SLAM2实时稠密地图,解决运行报段错误(核心已转储)运行数据集时出现段错误,出现可视化界面后闪退(添加实时彩色点云地图+保存点云地图)

高翔的稠密建图仓库 1. git clone https://github.com/gaoxiang12/ORBSLAM2_with_pointcloud_map.git 2. 去ORB SLAM2里拷贝Vocabulary到/home/cgm/ORBSLAM2_with_pointcloud_map/ORB_SLAM2_modified文件夹下 3. 删除一些build文件夹 删除ORB_SLAM2_modified/Thirdparty/DB…

国产手机芯片4G方案_紫光展锐安卓核心板虎贲4G智能模块方案定制

元器件清单即BOM物料清单&#xff0c;不同行业领域的BOM表侧重点不一样。安卓主板的BOM表则侧重点在于元器件物料的清单&#xff0c;也就是安卓电路板的PCBA清单&#xff0c;精密的安卓板有上千个物料&#xff0c;可以帮助我们估算物料成本&#xff0c;建立生产计划&#xff0c…

Ftp服务器、 Samba服务器、NFS服务器的区别

根据使用的方式来看&#xff0c;可以分为3种类别的文件服务器&#xff1a;ftp服务器&#xff08;ftp/tftp&#xff09;、 Samba服务器、NFS服务器。ftp的客户可以是任意平台&#xff0c;samba是专门针对windows客户&#xff0c;而NFS则是面向linux/unix用户的。下面是三种服务器…

CRM软件系统价格不同的原因

很多人在了解CRM系统时&#xff0c;发现不同品牌的CRM价格有着很大的区别。一些CRM系统只需要几千块钱&#xff0c;一些CRM系统的报价却要上万&#xff0c;甚至十几万。为什么CRM系统价格不同&#xff1f;下面我们就来说说。 1、功能不同 从功能方面来说&#xff0c;一些CRM系…