第10天-商品服务 - 分层领域模型及规格参数编码实现

news2024/11/30 14:28:37

1.分层领域模型规约

  • DO( Data Object): 此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
  • DTO( Data Transfer Object):数据传输对象, Service 或 Manager 向外传输的对象。
  • BO( Business Object):业务对象, 可以由 Service 层输出的封装业务逻辑的对象。
  • Query:数据查询对象,各层接收上层的查询请求。 注意超过 2 个参数的查询封装,禁止使用 Map
    类来传输。
  • VO( View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。


2.规格参数-新增

前端Vue

2.1.抽取VO对象

  • AttrEntity 的属性抽取到 AttrVO 对象中,并新增四个属性
    private Long attrGroupId;
    private String catelogName;
    private String groupName;
    private Long[] catelogPath;
  • Controller层的Handler处理方法入参统一使用 VO 对象
package com.atguigu.gmall.product.vo;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * 规格参数(基本属性) VO 对象
 *
 * @author zhangwen
 * @email 1466787185@qq.com
 * @date 2023-02-22 12:20:05
 */
@Data
public class AttrVO {
	/**
	 * 属性id
	 */
	private Long attrId;
	/**
	 * 属性名
	 */
	private String attrName;
	/**
	 * 是否需要检索[0-不需要,1-需要]
	 */
	private Integer searchType;
	/**
	 * 值类型[0-为单个值,1-可以选择多个值]
	 */
	private Integer valueType;
	/**
	 * 属性图标
	 */
	private String icon;
	/**
	 * 可选值列表[用逗号分隔]
	 */
	private String valueSelect;
	/**
	 * 属性类型[0-销售属性,1-基本属性,2-既是销售属性又是基本属性]
	 */
	private Integer attrType;
	/**
	 * 启用状态[0 - 禁用,1 - 启用]
	 */
	private Long enable;
	/**
	 * 所属分类
	 */
	private Long catelogId;
	/**
	 * 快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整
	 */
	private Integer showDesc;
	/**
	 * 属性分组Id
	 */
	private Long attrGroupId;
	/**
	 * 所属分类名
	 */
	private String catelogName;
	/**
	 * 所属分组名
	 */
	private String groupName;
	/**
	 * 三级分类完整路径
	 */
	private Long[] catelogPath;
}


2.2.商品常量类

gmall-common 公共服务中创建商品常量类 ProductConstant

package com.atguigu.common.constant;

/**
 * @Description:商品服务常量类
 * @Auther: zhangwen
 * @Date: 2023-02-22 10:51
 * @version: 1.0
 */
public class ProductConstant {
    /**
     * 属性枚举
     */
    public enum attrEnum{
        /**
         * 基本属性
         */
        ATTR_TYPE_BASE(1,"基本属性"),
        /**
         * 销售属性
         */
        ATTR_TYPE_SALE(0,"销售属性");

        private int code;
        private String msg;

        attrEnum(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
}    
    


2.3.API

POST /product/attr/save



2.4.后台接口实现

AttrController

 	/**
     * 保存规格参数
     */
    @RequestMapping("/save")
    public R save(@RequestBody AttrVO attrVO){
		attrService.saveAttr(attrVO);

        return R.ok();
    }

AttrServiceImpl

	/**
     * 保存规则参数
     * @param attrVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveAttr(AttrVO attrVO) {
        //保存基本属性
        AttrEntity attrEntity = new AttrEntity();
        //属性拷贝
        BeanUtils.copyProperties(attrVO, attrEntity);
        this.save(attrEntity);

        //保存关联关系 - 基本属性(只有规格参数需要和属性分组建立关系,销售属性不建立关系)
        if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrId(attrEntity.getAttrId());
            relationEntity.setAttrGroupId(attrVO.getAttrGroupId());
            relationDao.insert(relationEntity);
        }
    }


3.规格参数-列表查询



3.1.API

GET /product/attr/base/list/{catelogId}

//请求参数
{
	page: 1, //当前页码
	limit: 10, //每页记录数
	sidx: 'id', //排序字段
	order: 'asc', //排序方式
	key: '华为' //检索关键字
}

//响应数据
{
	"msg": "success",
	"code": 0,
	"page": {
	"totalCount": 0,
	"pageSize": 10,
	"totalPage": 0,
	"currPage": 1,
	"list": [{
		"attrId": 0, //属性id
		"attrName": "string", //属性名
		"attrType": 0, //属性类型,0-销售属性,1-基本属性
		"catelogName": "手机/数码/手机", //所属分类名字
		"groupName": "主体", //所属分组名字
		"enable": 0, //是否启用
		"icon": "string", //图标
		"searchType": 0, //是否需要检索[0-不需要,1-需要]
		"showDesc": 0, //是否展示在介绍上;0-否 1-是
		"valueSelect": "string", //可选值列表[用逗号分隔]
		"valueType": 0 //值类型[0-为单个值,1-可以选择多个值]
	}]
	}
}


3.2.后台接口实现

AttrController

	/**
     * 查询规格参数和销售属性列表
     * @param params 分页信息和查询关键字key
     * @param catelogId 三级分类ID
     * @param attrType 属性类型
     * @return
     */
     @GetMapping("/{attrType}/list/{catelogId}")
     public R listAttr(@RequestParam Map<String, Object> params,
					   @PathVariable("catelogId") Long catelogId, 
					   @PathVariable("attrType") String attrType) {
         PageUtils page = attrService.queryBaseAttrPage(params, catelogId, attrType);
         return R.ok().put("page", page);
     }

AttrServiceImpl

	/**
     * 查询规格参数和销售属性列表
     * @param params 分页信息和查询关键字key
     * @param catelogId 三级分类ID
     * @param attrType 属性类型
     * @return
     */
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String attrType) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>()
                .eq("attr_type","base".equalsIgnoreCase(attrType)
                        ? ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()
                        : ProductConstant.attrEnum.ATTR_TYPE_SALE.getCode());

        if(catelogId != 0){
            queryWrapper.eq("catelog_id",catelogId);
        }

        String key = (String)params.get("key");
        if(!StringUtils.isEmpty(key)){
            queryWrapper.and(wrapper ->{
                wrapper.eq("attr_id",key).or().like("attr_name",key);
            });
        }

        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), queryWrapper);

        PageUtils pageUtils = new PageUtils(page);
        //从分页对象中获取查询记录集
        List<AttrEntity> records = page.getRecords();
        List<AttrVO> attrVoList = records.stream().map(attrEntity -> {
            AttrVO attrVO = new AttrVO();
            BeanUtils.copyProperties(attrEntity, attrVO);

            //查询并设置分组名 groupName,基本属性需要显示分组,销售属性没有属性分组
            if ("base".equalsIgnoreCase(attrType)) {
                AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(
                        new QueryWrapper<AttrAttrgroupRelationEntity>()
                                .eq("attr_id", attrEntity.getAttrId()));
                if(relationEntity != null && relationEntity.getAttrGroupId() != null ){
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                    attrVO.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }

            //查询并设置分类名 catelogName
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if(categoryEntity != null){
                attrVO.setCatelogName(categoryEntity.getName());
            }
            return attrVO;
        }).collect(Collectors.toList());

        pageUtils.setList(attrVoList);

        return  pageUtils;
    }

运行结果如下:

在这里插入图片描述



4.规格参数-修改



4.1.所属分类及分组数据回显

在这里插入图片描述

4.1.1API

GET /product/attr/info/{attrId}
//响应数据
{
"msg": "success",
"code": 0,
"attr": {
	"attrId": 1,
	"attrName": "入网型号",
	"searchType": 1,
	"valueType": 1,
	"icon": "icon-1",
	"valueSelect": "v;q;w",
	"attrType": 1,
	"enable": 1,
	"showDesc": 1,
	"attrGroupId": 1, //分组id
	"catelogId": 225, //分类id
	"catelogPath": [2, 34, 225] //分类完整路径
	}
}

4.1.2后台接口实现

AttrController

	/**
     * 获取规格参数
     */
    @RequestMapping("/info/{attrId}")
    public R info(@PathVariable("attrId") Long attrId){
        AttrVO attrVO = attrService.getAttrInfo(attrId);

        return R.ok().put("attr", attrVO);
    }

AttrServiceImpl

	/**
     * 获取规格参数
     * @param attrId 属性id
     * @return 规格参数VO对象
     */
    @Override
    public AttrVO getAttrInfo(Long attrId) {
        AttrVO attrVO = new AttrVO();
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity,attrVO);

        //查询并设置分组名 groupName,基本属性需要显示分组,销售属性没有属性分组
        if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {
            AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(
                    new QueryWrapper<AttrAttrgroupRelationEntity>()
                            .eq("attr_id", attrEntity.getAttrId()));
            if (relationEntity != null && relationEntity.getAttrGroupId() != null) {
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                attrVO.setAttrGroupId(attrGroupEntity.getAttrGroupId());
                if (attrGroupEntity != null) {
                    attrVO.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }

        //查询并设置所属分类信息
        //一个微服务内部,service之间调用没有问题,考虑到开发便捷性和代码重用
        //对于是否违背设计原则,高内聚低耦合,本身微服务划分从根本上就已经做到了高内聚低耦合
        CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
        if(categoryEntity != null){
            attrVO.setCatelogName(categoryEntity.getName());
        }
        Long[] categoryPath = categoryService.findCategoryPath(attrEntity.getCatelogId());
        attrVO.setCatelogPath(categoryPath);
        
        return attrVO;
    }

运行结果:

在这里插入图片描述



4.2.修改规格参数


4.2.1.API

POST /product/attr/update


4.2.2.后台接口实现

AttrController

	/**
     * 修改规格参数
     */
    @RequestMapping("/update")
    public R update(@RequestBody AttrVO attrVO){
		attrService.updateAttr(attrVO);

        return R.ok();
    }

AttrServiceImpl

	/**
     * 修改规格参数
     * @param attrVO  规格参数VO对象
     */
    @Override
    public void updateAttr(AttrVO attrVO) {
        //修改基本信息
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVO,attrEntity);
        this.updateById(attrEntity);

        //修改分组关联 - 基本属性
        if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attrVO.getAttrGroupId());
            relationEntity.setAttrId(attrVO.getAttrId());

            Integer count = relationDao.selectCount(
                    new QueryWrapper<AttrAttrgroupRelationEntity>()
                            .eq("attr_id", attrVO.getAttrId()));
            if (count > 0) {
                //修改关联关系
                relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>()
                        .eq("attr_id", attrVO.getAttrId()));
            }else{
                //新增关联关系
                relationDao.insert(relationEntity);
            }
        }
    }

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

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

相关文章

VSCode远程连接服务器

工作使用服务器的jupyter&#xff0c;直到有一天服务器挂了&#xff0c;然而&#xff0c;代码还没有来得及备份。o(╥﹏╥)o VScode远程连接服务器&#xff0c;使用服务器的资源&#xff0c;代码可以存在本地&#xff0c;可以解决上述困境。 1.官网下载VSCode.网址https://cod…

JAVA并发集合之ConcurrentHashMap

ConcurrentHashMap是一个支持高并发更新与查询的哈希表(基于HashMap)。Hashmap在多线程并发的情况下&#xff0c;是线程不安全的&#xff0c;容易出现死循环、死锁等问题&#xff0c;JDK8后不会出现死锁问题&#xff0c;但依然存在多线程的系列问题&#xff0c;如&#xff1a;数…

数据结构_ 堆结构与堆排序(c++ 实现 + 完整代码 )

堆结构与堆排序 文章目录堆结构与堆排序引入堆堆结构所满足的数学特性准备代码----------- 往堆中插入元素----------- 删除堆顶堆排序构建完整代码及测试动态分配版本非动态版本引入堆 二叉树 具有左孩子与右孩子的最普通的二叉树。 满二叉树 特殊的二叉树&#xff1a;每个节…

sql join、left join、full join的区别总结,注意事项

1. 结论图 见 https://www.runoob.com/sql/sql-join.html 2. 测试 2.1. 造数据 数据表 mysql脚本 DROP TABLE IF EXISTS class; CREATE TABLE class (c_id INTEGER NOT NULL COMMENT 班级ID,c_name VARCHAR(100) NOT NULL COMMENT 班级名,PRIMARY KEY (c_id) ) CO…

JavaEE简单示例——动态SQL的复杂查询操作<foreach>

简单介绍&#xff1a; 在我们之前学习MySQL的时候&#xff0c;我们曾经有一个操作叫做查询区间&#xff0c;比如我们使用in关键字查询id为3到6之间的值&#xff0c;或者查询id小于100的值&#xff0c;这时候如果将SQL语句一条一条的查询出来进行筛选效率就太慢了&#xff0c;所…

【05-JVM面试专题-运行时数据区的结构都有哪些?哪些是共享的呢?哪些是非共享的呢?详细的介绍一下运行时数据区结构各部分的作用?】

运行时数据区的结构都有哪些&#xff1f;哪些是共享的呢&#xff1f;哪些是非共享的呢&#xff1f;详细的介绍一下运行时数据区结构各部分的作用&#xff1f; 运行时数据区的结构都有哪些&#xff1f;哪些是共享的呢&#xff1f;哪些是非共享的呢&#xff1f;详细的介绍一下运行…

带您了解TiDB MySQL数据库中关于日期、时间的坑

带您了解TiDB & MySQL数据库中关于日期、时间的坑时间的基础知识什么是时间计算时间的几种方法世界时&#xff08;UT&#xff09;协调世界时&#xff08;UTC&#xff09;国际原子时&#xff08;TAI&#xff09;时区的概念中国所在的时区操作系统的时区datetimedatectl数据库…

Spring代理模式——静态代理和动态代理

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

python打包exe实用工具auto-py-to-exe的操作方法

auto-py-to-exe操作方法auto-py-to-exe 是一个用于打包 python 程序的程序。本文就是主要介绍如何使用 auto-py-to-exe 完成 python 程序打包。本文主要分为两节&#xff0c;第一节主要对 auto-py-to-exe 做一些介绍&#xff0c;第二节则是演示 auto-py-to-exe 的打包过程。一、…

pygraphviz安装教程

0x01. 背景 最近在做casual inference&#xff0c;做实验时候想因果图可视化&#xff0c;遂需要安装pygraphviz&#xff0c;整了一下午&#xff0c;终于捣鼓好了&#xff0c;真头大。 环境&#xff1a; win10操作系统python3.9环境 0x02. 安装Graphviz 传送门&#xff1a;…

linux:本地套接字通信客户和服务器代码

客户端代码 #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <arpa/inet.h> #include <sys/un.h> int main(int argc, const cha…

中间件安全—Tomcat常见漏洞

中间件安全—Tomcat常见漏洞1.Tomcat常见漏洞1.1.前言1.2.文件上传 (CVE-2017-12615)1.2.1.漏洞原理1.2.2.影响版本1.2.3.漏洞复现1.2.3.1.测试是否允许PUT1.2.3.2.验证漏洞是否存在1.2.3.3.访问test.jsp1.2.3.4.上传执行命令脚本1.2.3.5.执行命令1.3.文件包含漏洞&#xff08;…

【第一章 - 绪论】- 数据结构(近八千字详解)

目录 一、 数据结构的研究内容 二、基本概念和术语 2.1 - 数据、数据元素、数据项和数据对象 2.2 - 数据结构 2.2.1 - 逻辑结构 2.2.2 - 存储结构 2.3 - 数据类型和抽象数据类型 三、抽象数据类型的表现与实现 四、算法和算法分析 4.1 - 算法的定义及特性 4.2 - 评价…

手把手教大家在 gRPC 中使用 JWT 完成身份校验

文章目录1. JWT 介绍1.1 无状态登录1.1.1 什么是有状态1.1.2 什么是无状态1.2 如何实现无状态1.3 JWT1.3.1 简介1.3.2 JWT数据格式1.3.3 JWT 交互流程1.3.4 JWT 存在的问题2. 实践2.1 项目创建2.2 grpc_api2.3 grpc_server2.4 grpc_client3. 小结上篇文章松哥和小伙伴们聊了在 …

Docker 如何配置镜像加速

Docker 镜像加速 国内从 DockerHub 拉取镜像有时会遇到困难&#xff0c;此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务&#xff0c;例如&#xff1a; 科大镜像&#xff1a;https://docker.mirrors.ustc.edu.cn/网易&#xff1a;https://hub-…

生态流量数据采集传输协议定制开发(嵌入式水资源SZY206协议以及VC++ POST数据发送)

水电站生态流量在线监测&#xff0c;流量数据采集传输,水资源遥测终端机程序。 背景&#xff1a;现场使用SCJ-LL01多普勒超声波流量计采集生态下泄流量&#xff0c;使用太阳能供电系统&#xff0c;使用SCJ-RTU01遥测终端机进行数据采集&#xff0c;设备采用4G通讯&#xff0c;…

基于MATLAB开发AUTOSAR软件应用层模块-part23.SR interface通信介绍(接收的数据错误时应该如何处理)

在软件SWC之间的AUTOSAR SR通信中,当COM报告接收SWC的数据接收错误时,运行时环境(RTE)触发DataReceiveErrorEvent。该事件可以指示发送方SWC未能在AliveTimeout限制内回复,或者发送方SWC发送了无效数据。 接下来我们就讲解下怎么实现无效数据的接收和判断 还是三步走,建模…

Ubuntu 上 Let‘s Encrypt 生成泛域名证书

安装生成工具certbot&#xff1a; apt install certbot 查看安装在哪&#xff1a; which certbot 使用certbot&#xff08;位置在 /usr/bin/certbot&#xff09;生成证书&#xff1a; /usr/bin/certbot certonly -d *.xxx.com --manual --preferred-challenges dns --ser…

一种全新的图像滤波理论的实验(二)

一、前言 2021年12月31日&#xff0c;我发布了基于加权概率模型的图像滤波算法的第一个实验&#xff0c;当时有两个关键问题没有解决&#xff1a; 1、出现了大面积的黑色区域&#xff0c;最近考虑把这个算法实际应用在图像和视频的压缩领域&#xff0c;于是通过对程序的分析&a…

【论文简述】GMFlow: Learning Optical Flow via Global Matching(CVPR 2022)

一、论文简述 1. 第一作者&#xff1a;Haofei Xu 2. 发表年份&#xff1a;2022 3. 发表期刊&#xff1a;CVPR oral 4. 关键词&#xff1a;光流、代价体、Transformers、全局匹配、注意力机制 5. 探索动机&#xff1a;过去几年中具有代表性的光流学习框架的核心估计方式没有…