乐优商城项目总结——07商品规格管理(spu,sku)

商品管理

商品的管理不能像以前写的小demo一样,一个表解决所有的问题。
全品类的商品种类很多,商品的属性也不一样,存到一起商品又多又难管理。所以抽出来两个概念:spu和sku

商品管理的难点就在于搞清楚商品spu和sku,搞清楚以后业务逻辑很容易实现。

SPU和SKU

SPU:Standard Product Unit (标准产品单位) ,一组具有共同属性的商品集

SKU:Stock Keeping Unit(库存量单位),SPU商品集因具体特性不同而细分的每个商品

下面从网上找到一个商品解释一下:

在这里插入图片描述

  • 小米Redmi K20Pro 就是一个商品集(SPU)
  • 因为颜色、内存等不同,而细分出不同的 小米Redmi K20Pro,比如冰川蓝8+128GB。(SKU)

所以spu是一个抽象的概念,我们实际买的某一个颜色某一个版本的手机是sku。
买的是sku

数据库设计

弄清楚了SPU和SKU的概念,就该考虑一下数据库怎么设计了。

SKU的特有属性

SPU中会有一些特殊属性,用来区分不同的SKU,我们称为SKU特有属性。如小米手机的颜色、内存属性。

不同种类的商品,一个手机,一个衣服,其SKU属性不相同。

同一种类的商品,比如都是衣服,SKU属性基本是一样的,都是颜色、尺码等。

SKU的特有属性是商品规格参数的一部分:在这里插入图片描述
所以可以不用对sku特有属性进行设计,因为他存在于规格参数中,是规格参数的一部分。

  • 所有sku共享的规格属性(称为全局属性)
  • 每个sku不同的规格属性(称为特有属性)
    在这里插入图片描述
    而搜索的时候也会用到规格参数的一部分,这些参数都可以在规格参数中找到,需要哪个字段做过滤可以给它做一个标识。
    在这里插入图片描述
    在这里插入图片描述

具体数据库表

我们观察页面的规格参数结构:
在这里插入图片描述
可以看到规格参数是分组的,每一组都有多个参数键值对。不过对于规格参数的模板而言,其值现在是不确定的,不同的商品值肯定不同,模板中只要保存组信息、组内参数信息即可。

设计两张表:

  • tb_spec_group:规格参数组,与商品分类关联
  • tb_spec_param:规格参数,与组关联,一对多(竖表设计,把参数名作为字段)
    -在这里插入图片描述

可以看到下图,group表里存的是那些组名称,它们都绑定到一个cid(分类的id),而param表里存的是每个组里面键值对的键(key),它们也都绑定到一个cid,这是为根据分类查找所有规格参数,页面展示,搜索过滤的时候会有用(而不用再通过tb_spec_group)。而键值对的值value是不确定的,它们存在spu,spu_detail,sku这些表中。

tb_spec_group:

在这里插入图片描述
tb_spec_param:
后面加的字段是对参数数值进行要求,比如上市年份只能输入几几年,而不能输入文字等乱七八糟的,还有是否要作为过滤条件(搜索过滤时候用)
在这里插入图片描述

代码实现

controller:

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

    /**
     * 根据分类id查询规格组
     *
     * @param cid
     * @return
     */
    @GetMapping("groups/{cid}")
    public ResponseEntity<List<SpecGroup>> queryByCid(@PathVariable("cid") Long cid) {
        List<SpecGroup> specGroups = specificationService.queryGroupByCid(cid);
        return ResponseEntity.ok(specGroups);
    }

    /**
     * 跟据组id查询参数
     * 第二次改:查询参数集合
     *
     * @param gid
     * @param gid       规格组ID
     * @param cid       商品分类ID
     * @param searching 是否是搜索字段
     * @param generic   是否是通用字段
     * @return
     */
    @GetMapping("params")
    public ResponseEntity<List<SpecParam>> queryParamByList(
            @RequestParam(value = "gid", required = false) Long gid,
            @RequestParam(value = "cid", required = false) Long cid,
            @RequestParam(value = "searching", required = false) Boolean searching,
            @RequestParam(value = "generic", required = false) Boolean generic) {

        return ResponseEntity.ok(specificationService.queryParamByList(gid, cid, searching, generic));
    }

    /**
     * 根据分类查询规格组及组内参数
     *
     * @param cid
     * @return
     */
    @GetMapping("group")
    public ResponseEntity<List<SpecGroup>> queryListByCid(@RequestParam("cid") Long cid) {
        return ResponseEntity.ok(specificationService.queryListByCid(cid));
    }
}

service:

@Service
public class SpecificationService {
    @Autowired
    private SpecGroupMapper groupMapper;
    @Autowired
    private SpecParamMapper paramMapper;

    /**
     * 根据分类id查询规格组
     *
     * @param cid
     * @return
     */
    public List<SpecGroup> queryGroupByCid(Long cid) {
        SpecGroup g = new SpecGroup();
        g.setCid(cid);
        List<SpecGroup> select = groupMapper.select(g);
        if (CollectionUtils.isEmpty(select)) {
            throw new LyException(ExceptionEnum.SPEC_GROUP_NOT_FOUND);
        }
        return select;
    }

    /**
     * 跟据组id查询参数
     *
     * @param gid
     * @return
     */
    public List<SpecParam> queryParamByList(Long gid, Long cid, Boolean searching, Boolean generic) {
        SpecParam p = new SpecParam();
        p.setGroupId(gid);
        p.setCid(cid);
        p.setSearching(searching);
        p.setGeneric(generic);


        List<SpecParam> select1 = paramMapper.select(p);
        if (CollectionUtils.isEmpty(select1)) {
            throw new LyException(ExceptionEnum.SPEC_PARAM_NOT_FOUND);
        }
        return select1;
    }

    /**
     * 根据分类查询规格组及组内参数
     *
     * @param cid
     * @return
     */
    public List<SpecGroup> queryListByCid(Long cid) {
//        查询规格组
        List<SpecGroup> specGroups = queryGroupByCid(cid);
//        查询当前分类下的参数
        List<SpecParam> specParams = queryParamByList(null, cid, null, null);
//        把规格参数变成map,key是规格组id,value是组内的所有参数
        Map<Long, List<SpecParam>> map = new HashMap<>();
        for (SpecParam param : specParams) {
            if (!map.containsKey(param.getGroupId())) {
//                这个组id在map中不存在,新增一个list
                map.put(param.getGroupId(), new ArrayList<>());
            }
            map.get(param.getGroupId()).add(param);
        }
//        填充param到group
        for (SpecGroup specGroup : specGroups) {
            specGroup.setParams(map.get(specGroup.getId()));
        }

        return specGroups;
    }
}

总结:

了解spu和sku,商品分类和规格组表,规格参数表的关系后,业务逻辑实现就会简单,因为要从哪张表查数据,需要查的spu还是sku就知道了,写代码的整套流程就会清晰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值