文章目录

  • 7.1 平台属性-规格参数
  • 7.11 新增规格参数
  • 7.12 查询分类规格参数列表
  • 7.13 查询属性详情
  • 7.14 修改规格参数
  • 7.2 平台属性-销售属性
  • 7.3 属性分组关联
  • 7.31 属性分组关联属性
  • 7.32 移除属性与分组的关联关系
  • 7.33 查询属性分组未关联的所有属性
  • 7.34 添加属性与分组关联关系(点击确认新增)



平台属性用到三张表


谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据


① 进入平台属性—》规格参数—》新增


谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_02


数据库保存的数据,就是新增的属性数据:(pms_attr属性表)


谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_03


② 进入平台属性—》属性分组—》关联:

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_04


属性分组表如下:

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_ide_05


③点击关联,增加后保存的数据是在关联表如下:属性分组与属性的关联表。

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_ide_06

7.1 平台属性-规格参数

7.11 新增规格参数

① 在com.atguigu.gulimall.product.vo包下新建一个AttrVo对象,用于接收页面提交的请求数据,这个AttrVo对象就是比AttrEntity实体类多了一个字段attrGroupId,并且该字段不在数据库中:

AttrVo

@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;

    //多余的参数,不在数据库中
    private Long attrGroupId;
}

② 在AttrController中修改新增属性的方法:

@RequestMapping("/save")
public R save(@RequestBody AttrVo attr){
    attrService.saveAttr(attr);
    return R.ok();
}

③ 在attr表中保存基本属性信息,然后在关联表中保存关联信息,在AttrServiceImpl类中:

@Autowired
private AttrAttrgroupRelationDao relationDao;

@Transactional
    @Override
    public void saveAttr(AttrVo attr) {//这个attr是前端页面传过来的数据,与VO数据:AttrVo对应
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);//将attr的数据(AttrVo对应)复制到attrEntity实体类中的数据
        //保存基本数据
        this.save(attrEntity);
        //保存关联数据
        AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
        //将以下的AttrGroupId(属性分组id)、AttrId(属性id)设置到属性与属性分组关联表中
        relationEntity.setAttrGroupId(attr.getAttrGroupId());
        relationEntity.setAttrId(attrEntity.getAttrId());
        relationDao.insert(relationEntity);//保存进数据库
    }

④ 测试:新增属性

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_07


对应的relation关联表(属性id1和2都对应着属性分组1)

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_08

7.12 查询分类规格参数列表

前端API:https://easydoc.xyz/s/78237135/ZUqEdvA4/Ld1Vfkcd

① 请求路径:/product/attr/base/list/{catelogId},分页查询,模糊查询

② 在AttrController中:

@RequestMapping("/base/list/{catelogId}")
public R list(@RequestParam Map<String, Object> params,
              @PathVariable("catelogId") Long catelogId){
    PageUtils page = attrService.queryBaseAttrPage(params,catelogId);
    return R.ok().put("page",page);
}

③ 在AttrServiceImpl类中:

@Override
public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId) {
    QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
    if(catelogId!=0){
        queryWrapper.eq("catelog_id",catelogId);
    }
    String key = (String) params.get("key");
    if(!StringUtils.isEmpty(key)){
        //attr_id=key 或者 attr_name like %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);
    return new PageUtils(page);
}

重启项目,查看规格参数,可以看到在响应数据时还需要响应所属分类和所属分组(缺少),可以参考API前端文档。

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_09


④在vo包下创建 响应对象AttrRespVo,比AttrEntity多了所属分类和所属分组:

@Data
public class AttrRespVo extends AttrVo {
    /**
     *   "catelogName": "手机/数码/手机", //所属分类名字
     *   "groupName": "主体", //所属分组名字
     */
    private String catelogName;
    private String groupName;
}

⑤ 在AttrServiceImpl类中修改queryBaseAttrPage()方法:

@Resource
private AttrGroupDao attrGroupDao;
@Resource
private CategoryDao categoryDao;
@Override
public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId) {
    QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>();

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

    String key = (String) params.get("key");
    if(!StringUtils.isEmpty(key)){
        //attr_id  attr_name
        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<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
        AttrRespVo attrRespVo = new AttrRespVo();
        BeanUtils.copyProperties(attrEntity, attrRespVo);

        //查询一条记录
        AttrAttrgroupRelationEntity attrId = relationDao.selectOne(
                new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
        //根据attrId查询出AttrGroupEntity,然后查询出AttrGroupName
        if (attrId != null) {
            AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrId.getAttrGroupId());
            attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
        }
        CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
        if (categoryEntity != null) {
            attrRespVo.setCatelogName(categoryEntity.getName());
        }
        return attrRespVo;
    }).collect(Collectors.toList());
    pageUtils.setList(respVos);
    return pageUtils;
}

再次测试,发现已经加上了所属分类和所属分组

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_10

7.13 查询属性详情

需求:在修改规格参数时,希望回显所属分类(分类的完整路径)和所属分组

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_ide_11


前端接口API:https://easydoc.xyz/s/78237135/ZUqEdvA4/7C3tMIuF如下:

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_12


① AttrRespVo中编写需要响应的字段:

@Data
public class AttrRespVo extends AttrVo {
    private String catelogName;
    private String groupName;
    private Long[] catelogPath;//这里添加分类完整路径
}

② 在AttrController中修改info()方法,加上响应字段:

@RequestMapping("/info/{attrId}")
public R info(@PathVariable("attrId") Long attrId){
    //    AttrEntity attr = attrService.getById(attrId);,原先这个AttrEntity返回消息太少
    //返回响应AttrRespVo,这个自定义的实体类,返回的消息多
    AttrRespVo respVo = attrService.getAttrInfo(attrId);
    return R.ok().put("attr", respVo);
}

③ 在AttrServiceImpl类中:

@Override
public AttrRespVo getAttrInfo(Long attrId) {
    AttrRespVo respVo = new AttrRespVo();
    AttrEntity attrEntity = this.getById(attrId);
    //将attrEntity中的基本属性拷贝到respVo
    BeanUtils.copyProperties(attrEntity,respVo);
    
    //1、设置分组信息
    //查询一条记录,条件为:attr_id=attrId,前端传过来的数据属性id:attrId,通过它查询属性与属性分组关联表(pms_attr_attrgroup_relation)的信息
    AttrAttrgroupRelationEntity attrgroupRelation = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
    if(attrgroupRelation!=null){
        //设置attr_group_id和attr_groupname字段
        respVo.setAttrGroupId(attrgroupRelation.getAttrGroupId());
        //attrGroupEntity分组表
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupRelation.getAttrGroupId());
        if(attrGroupEntity!=null){
            respVo.setGroupName(attrGroupEntity.getAttrGroupName());
        }
    }

    //2、设置分类信息
    Long catelogId = attrEntity.getCatelogId();
    Long[] catelogPath = categoryService.findCatelogPath(catelogId);
    respVo.setCatelogPath(catelogPath);

    CategoryEntity categoryEntity = categoryDao.selectById(catelogId);
    if(categoryEntity!=null){
        respVo.setCatelogName(categoryEntity.getName());
    }
    return respVo;
}

测试:点击修改,可以显示所属分类和所属分组,但是当修改所属分组后,保存不成功,因为我们只做了新增的功能save(),并没有完成修改保存的功能,即修改update()方法:

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_13

7.14 修改规格参数

① 在AttrController中:修改update方法

@RequestMapping("/update")
public R update(@RequestBody AttrVo attr){
    attrService.updateAttr(attr);
    return R.ok();
}

② 在AttrServiceImpl类中:

@Transactional
@Override
public void updateAttr(AttrVo attr) {
    AttrEntity attrEntity = new AttrEntity();
    BeanUtils.copyProperties(attr,attrEntity);
    this.updateById(attrEntity);

    //1、修改分组关联
    AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();

    relationEntity.setAttrGroupId(attr.getAttrGroupId());
    relationEntity.setAttrId(attr.getAttrId());

    Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
    if(count>0){
        relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId()));
    }else{
        relationDao.insert(relationEntity);
    }

7.2 平台属性-销售属性

销售属性与规格参数不一样,它不需要和属性分组关联。所以需要做一些attr_type(属性类别)的判断。

① 前端API接口文档:https://easydoc.xyz/s/78237135/ZUqEdvA4/FTx6LRbR

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_ide_14


② 数据库分析:对于pms_attr这张表,既存放了规格参数(基本属性),又存放了销售属性,当attr_type=0时代表销售属性,当attr_type=1时代表规格参数

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_15


③在gulimall-common创建一个attr_type(属性分类判断)

attr_type=1:规格参数(基本属性);attr_type=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 String getMsg() {
            return msg;
        }
    }
}

④修改AttrServiceImpl的一些方法,只有当attr_type=1:规格参数(基本属性)时,才会进行保存,修改,所以需要加判断

//-----saveAttr:属性保存时代码
@Transactional
    @Override
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
//        attrEntity.setAttrName(attr.getAttrName());
        BeanUtils.copyProperties(attr,attrEntity);
        //1、保存基本数据
        this.save(attrEntity);
        //2、保存关联关系,只有attr_type=1:规格参数(基本属性)时
        if(attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId()!=null){
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            relationEntity.setAttrId(attrEntity.getAttrId());
            relationDao.insert(relationEntity);
        }
    }

//--------------queryBaseAttrPage 查询属性,添加type属性判断
@Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {
        //此处模糊查询,不用判断,规格参数和销售属性 都需要模糊查询
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("attr_type","base".equalsIgnoreCase(type)?ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());
       //.............省略
        
            //1、设置分类和分组的名字
            if("base".equalsIgnoreCase(type)){//判断
                AttrAttrgroupRelationEntity attrId = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
                //前面有代码,此处省略.........
    }

//--------------------getAttrInfo:属性详情
        @Override
    public AttrRespVo getAttrInfo(Long attrId) {
        AttrRespVo respVo = new AttrRespVo();
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity,respVo);
//判断是否是基本属性
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //1、设置分组信息
            AttrAttrgroupRelationEntity attrgroupRelation = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
//.....................省略
    }
        
//------------------updateAttr:更新属性
@Transactional
    @Override
    public void updateAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);
        this.updateById(attrEntity);
//判断是否是基本属性,是就执行
        if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            //1、修改分组关联
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
//...........省略

⑤AttrController的修改

//product/attr/sale/list/0?
    ///product/attr/base/list/{catelogId}
    @GetMapping("/{attrType}/list/{catelogId}")
    public R baseAttrList(@RequestParam Map<String, Object> params,
                          @PathVariable("catelogId") Long catelogId,
                          @PathVariable("attrType")String type){

        PageUtils page = attrService.queryBaseAttrPage(params,catelogId,type);
        return R.ok().put("page", page);
    }

⑥测试:

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_ide_16


销售属性都不关联属性分组

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_17


谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_18

7.3 属性分组关联

7.31 属性分组关联属性

① 获取指定属性分组关联的所有属性:获取属性分组的关联的所有属性

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_19


接口文档:https://easydoc.xyz/s/78237135/ZUqEdvA4/LnjzZHPj

②在AttrGroupController中,根据attrgroupId找到组内关联的所有属性:

@RequestMapping("/{attrgroupId}/attr/relation")
public R attrRelation(@PathVariable("attrgroupId") Long attrgroupId){
    List<AttrEntity> entities = attrService.getRelationAttr(attrgroupId);
    return R.ok().put("data",entities);
}

③AttrServiceImpl添加以下方法

/* *
 * 根据分组id查找关联的所有基本属性
 * @param attrgroupId
 * @return
 */
@Override
public List<AttrEntity> getRelationAttr(Long attrgroupId) {
    List<AttrAttrgroupRelationEntity> entities = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId));

    List<Long> attrIds = entities.stream().map((attr) -> {
        return attr.getAttrId();
    }).collect(Collectors.toList());

    if(attrIds == null || attrIds.size() == 0){
        return null;
    }
    Collection<AttrEntity> attrEntities = this.listByIds(attrIds);
    return (List<AttrEntity>) attrEntities;
}

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_20

7.32 移除属性与分组的关联关系

接口文档:https://easydoc.xyz/s/78237135/ZUqEdvA4/qn7A2Fht

属性并不删除,只是移除属性和分组之间的关联关系而已,

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_基本属性_21


①在AttrGroupController中:

//请求参数:[{"attrId":1,"attrGroupId":2}]
@PostMapping("/attr/relation/delete")
public R deleteRelation( @RequestBody AttrGroupRelationVo[] vos){
    attrService.deleteRelation(vos);
    return R.ok();
}

②在vo包下自定义AttrGroupRelationVo

@Data
public class AttrGroupRelationVo {
    private Long attrId;
    private Long attrGroupId;
}

③在AttrServiceImpl中:

@Override
public void deleteRelation(AttrGroupRelationVo[] vos) {
    List<AttrAttrgroupRelationEntity> entities = Arrays.asList(vos).stream().map((item) -> {
        AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
        BeanUtils.copyProperties(item, relationEntity);
        return relationEntity;
    }).collect(Collectors.toList());
    //批量移除属性分组和属性的关联关系
    relationDao.deleteBatchRelation(entities);
}

④下面要做的就是自己手动的写sql语句,实现deleteBatchRelation(entities)方法:

<delete id="deleteBatchRelation">
    DELETE FROM `pms_attr_attrgroup_relation` WHERE
    <foreach collection="entities" item="item" separator=" OR ">
        (attr_id=#{item.attrId} AND attr_group_id=#{item.attrGroupId})
    </foreach>
</delete>

⑤当执行测试时,点移除,发现pms_attr_attrgroup_relation表的关联数据被删除,

但是pms_attr的属性并没有删除(因为没有点规格参数或销售属性栏的删除按钮)

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_22

7.33 查询属性分组未关联的所有属性

需求分析:点击关联后,新建关联,获取属性分组里面还没有关联的本分类里面的其他基本属性(规格参数),方便添加新的关联

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_ide_23


前端接口文档:https://easydoc.xyz/s/78237135/ZUqEdvA4/d3EezLdO

在AttrGroupController中:

//获取当前分组没有关联的所有属性
@RequestMapping("/{attrgroupId}/noattr/relation")
public R attrNoRelation(@PathVariable("attrgroupId") Long attrgroupId,
                        @RequestParam Map<String,Object> params){
    PageUtils page =  attrService.getNoRelationAttr(params,attrgroupId);
    return R.ok().put("page",page);
}

在AttrServiceImpl中:

@Override
public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
    //1、当前分组只能关联自己所属的分类里面的所有属性
    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
    Long catelogId = attrGroupEntity.getCatelogId();
    //2、当前分组只能关联别的分组没有引用的属性
    //2.1)、当前分类下的所有分组
    List<AttrGroupEntity> group = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
    //获取所有分组的group_id集合
    List<Long> collect = group.stream().map(item -> {
        return item.getAttrGroupId();
    }).collect(Collectors.toList());

    //2.2)、这些分组关联的属性,groupId是属性集合
    List<AttrAttrgroupRelationEntity> groupId = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", collect));
    //获取属性id集合(attr_id)
    List<Long> attrIds = groupId.stream().map(item -> {
        return item.getAttrId();
    }).collect(Collectors.toList());

    //2.3)、从当前分类的所有属性中移除这些属性;
    QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>().eq("catelog_id", catelogId).eq("attr_type",ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
    if(attrIds!=null && attrIds.size()>0){
        wrapper.notIn("attr_id", attrIds);
    }
    String key = (String) params.get("key");
    if(!StringUtils.isEmpty(key)){
        wrapper.and((w)->{
            w.eq("attr_id",key).or().like("attr_name",key);
        });
    }
    IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);

    PageUtils pageUtils = new PageUtils(page);

    return pageUtils;
}

谷粒商城 创建redisson配置文件 测试RedissonClient报错 谷粒网站_数据_24

7.34 添加属性与分组关联关系(点击确认新增)

前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/VhgnaedC

AttrGroupController

@RequestMapping("/attr/relation")
public R addRelation(@RequestBody List<AttrGroupRelationVo> vos){
    relationService.saveBatch(vos);
    return R.ok();
}

AttrAttrgroupRelationServiceImpl

@Override
public void saveBatch(List<AttrGroupRelationVo> vos) {
    List<AttrAttrgroupRelationEntity> collect = vos.stream().map((item) -> {
        AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
        BeanUtils.copyProperties(item, relationEntity);
        return relationEntity;
    }).collect(Collectors.toList());
    this.saveBatch(collect);
}