谷粒商城--平台属性模块--笔记八

谷粒商城–平台属性模块–笔记八

接口参考文档

1.品牌分类关联与级联更新

1.mybatis-plus分页组件未生效

谷粒商城--平台属性模块--笔记八

解决

新增配置文件com/atguigu/gulimall/product/config/MyBatisConfig.java

package site.zhourui.gulimall.product.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement //开启事务
@MapperScan("site.zhourui.gulimall.product.dao")
public class MyBatisConfig {

    //引入分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        paginationInterceptor.setOverflow(true);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInterceptor.setLimit(1000);
        return paginationInterceptor;
    }
}

重启后分页生效

谷粒商城--平台属性模块--笔记八

2.模糊查询不生效问题

谷粒商城--平台属性模块--笔记八

解决

修改gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/BrandServiceImpl.java 的queryPage方法

@Override
    public PageUtils queryPage(Map<String, Object> params) {
        //1、获取key
        String key = (String) params.get("key");
        QueryWrapper<BrandEntity> queryWrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(key)){
            queryWrapper.eq("brand_id",key).or().like("name",key);
        }

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

        );

        return new PageUtils(page);
    }

效果

谷粒商城--平台属性模块--笔记八

3.前端代码

将文档中的common和product文件夹复制到自己的目录下

谷粒商城--平台属性模块--笔记八

重启项目 npm run dev

商品管理相关的前端代码都有了

谷粒商城--平台属性模块--笔记八

4.品牌与分类关联

多对多关系

谷粒商城--平台属性模块--笔记八

1.品牌分类关联列表查询接口

gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/CategoryBrandRelationController.java新增接口

	/**
     * 获取当前品牌关联的所有分类列表
     */
    @GetMapping("/catelog/list")
    //@RequiresPermissions("product:categorybrandrelation:list")
    public R cateloglist(@RequestParam("brandId")Long brandId){
        List<CategoryBrandRelationEntity> data = categoryBrandRelationService.list(
                new QueryWrapper<CategoryBrandRelationEntity>().eq("brand_id",brandId)
        );

        return R.ok().put("data", data);
    }

效果

谷粒商城--平台属性模块--笔记八

2.品牌分类关联新增接口

原因:电商系统数据量大,少用连表查询,尽量用分库分表查询

逆向工程生成的保存方法只传入了brandIdcatelogId并没有传入name

所以新增关联后品牌名与分类名为空

谷粒商城--平台属性模块--笔记八

解决

修改save方法,根据brandIdcatelogId查询出存入品牌名与分类名在存入

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/CategoryBrandRelationService.java

void saveDetail(CategoryBrandRelationEntity categoryBrandRelation);

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/CategoryBrandRelationServiceImpl.java

    @Override
    public void saveDetail(CategoryBrandRelationEntity categoryBrandRelation) {
        Long brandId = categoryBrandRelation.getBrandId();
        Long catelogId = categoryBrandRelation.getCatelogId();
        //1、查询详细名字
        BrandEntity brandEntity = brandDao.selectById(brandId);
        CategoryEntity categoryEntity = categoryDao.selectById(catelogId);

        categoryBrandRelation.setBrandName(brandEntity.getName());
        categoryBrandRelation.setCatelogName(categoryEntity.getName());

        this.save(categoryBrandRelation);

    }

gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/CategoryBrandRelationController.java 修改save方法

	/**
     * 保存
     */
    @RequestMapping("/save")
    //@RequiresPermissions("product:categorybrandrelation:save")
    public R save(@RequestBody CategoryBrandRelationEntity categoryBrandRelation){


		categoryBrandRelationService.saveDetail(categoryBrandRelation);

        return R.ok();
    }

重启测试

新增后,品牌名与分类名都保存了

谷粒商城--平台属性模块--笔记八

分库分表冗余数据出现的问题

比如品牌表中的品牌名或分类表中的分类名发生变化,关联表中的品牌名与分类名不会变化

如下:品牌名已经为华为1但关联表中的品牌名仍为华为

谷粒商城--平台属性模块--笔记八

解决办法:处理时同步更新

使品牌名更新时,同步更新关联表

使分类名更新时,同步更新关联表

1.品牌关联类目

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/CategoryBrandRelationService.java

用做关联表中的品牌,分类名,其他service调用

void updateBrand(Long brandId, String name);
void updateCategory(Long catId, String name);

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/CategoryBrandRelationServiceImpl.java

@Override
public void updateBrand(Long brandId, String name) {
    CategoryBrandRelationEntity relationEntity = new CategoryBrandRelationEntity();
    relationEntity.setBrandId(brandId);
    relationEntity.setBrandName(name);
    this.update(relationEntity,new UpdateWrapper<CategoryBrandRelationEntity>().eq("brand_id",brandId));
}

@Override
public void updateCategory(Long catId, String name) {
    this.baseMapper.updateCategory(catId,name);
}
1.品牌

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/BrandService.java 新增接口

void updateDetail(BrandEntity brand);

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/BrandServiceImpl.java 新增接口

@Transactional
@Override
public void updateDetail(BrandEntity brand) {
    //保证冗余字段的数据一致
    this.updateById(brand);
    if(!StringUtils.isEmpty(brand.getName())){
        //同步更新其他关联表中的数据
        categoryBrandRelationService.updateBrand(brand.getBrandId(),brand.getName());

        //TODO 更新其他关联
    }
}

gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/BrandController.java 修改update方法

	/**
     * 修改
     */
    @RequestMapping("/update")
    //@RequiresPermissions("product:brand:update")
    public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand){
        brandService.updateDetail(brand);

        return R.ok();
    }
2.类目

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/CategoryService.java

void updateCascade(CategoryEntity category);

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/CategoryServiceImpl.java

    /**
     * 级联更新所有关联的数据
     * @param category
     */
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }

gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/CategoryController.java 修改update方法

	/**
     * 修改
     */
    @RequestMapping("/update")
    //@RequiresPermissions("product:category:update")
    public R update(@RequestBody CategoryEntity category){
        categoryService.updateCascade(category);
        return R.ok();
    }

效果

修改手机分类名为手机1

谷粒商城--平台属性模块--笔记八

关联表中也会改变,修改品牌名同理

谷粒商城--平台属性模块--笔记八

2.Object 划分

1.PO(persistant object) 持久对象

PO 就是对应数据库中某个表中的一条记录, 多个记录可以用 PO 的集合。 PO 中应该不包含任何对数据库的操作。

2.DO(Domain Object) 领域对象

就是从现实世界中抽象出来的有形或无形的业务实体。

3.TO(Transfer Object) , 数据传输对象

不同的应用程序之间传输的对象

4.DTO(Data Transfer Object) 数据传输对象

这个概念来源于 J2EE 的设计模式, 原来的目的是为了 EJB 的分布式应用提供粗粒度的数据实体, 以减少分布式调用的次数, 从而提高分布式调用的性能和降低网络负载, 但在这里, 泛指用于展示层与服务层之间的数据传输对象。

5.VO(value object) 值对象

通常用于业务层之间的数据传递, 和 PO 一样也是仅仅包含数据而已。 但应是抽象出的业务对象 , 可以和表对应 , 也可以不 , 这根据业务的需要 。 用 new 关键字创建, 由GC 回收的。
View object: 视图对象;
接受页面传递来的数据, 封装对象
将业务处理完成的对象, 封装成页面要用的数据

6.BO(business object) 业务对象

从业务模型的角度看 , 见 UML 元件领域模型中的领域对象。 封装业务逻辑的 java 对象 , 通过调用 DAO 方法 , 结合 PO,VO 进行业务操作。 business object: 业务对象 主要作用是把业务逻辑封装为一个对象。 这个对象可以包括一个或多个其它的对象。 比如一个简历, 有教育经历、 工作经历、 社会关系等等。 我们可以把教育经历对应一个 PO , 工作经历对应一个 PO , 社会关系对应一个 PO 。 建立一个对应简历的 BO 对象处理简历, 每个 BO 包含这些 PO 。 这样处理业务逻辑时, 我们就可以针对 BO 去处理。

7.POJO(plain ordinary java object) 简单无规则 java 对象

传统意义的 java 对象。 就是说在一些 Object/Relation Mapping 工具中, 能够做到维护数据库表记录的 persisent object 完全是一个符合 Java Bean 规范的纯 Java 对象, 没有增加别的属性和方法。 我的理解就是最基本的 java Bean , 只有属性字段及 setter 和 getter方法! 。
POJO 是 DO/DTO/BO/VO 的统称。

8.DAO(data access object) 数据访问对象

是一个 sun 的一个标准 j2ee 设计模式, 这个模式中有个接口就是 DAO , 它负持久层的操作。 为业务层提供接口。 此对象用于访问数据库。 通常和 PO 结合使用, DAO 中包含了各种数据库的操作方法。 通过它的方法 , 结合 PO 对数据库进行相关的操作。 夹在业务逻辑与数据库资源中间。 配合 VO, 提供数据库的 CRUD 操作

3.属性分组模块

1.新建所需VO

1.原因

规格参数新增时,请求的URL:Request URL:

http://localhost:88/api/product/attr/base/list/0?t=1588731762158&page=1&limit=10&key=

当有新增字段时,我们往往会在entity实体类中新建一个字段,并标注数据库中不存在该字段,然而这种方式并不规范

谷粒商城--平台属性模块--笔记八

比较规范的做法是,新建一个vo文件夹,将每种不同的对象,按照它的功能进行了划分。在java中,涉及到了这几种类型

谷粒商城--平台属性模块--笔记八

Request URL: http://localhost:88/api/product/attr/save,现在的情况是,它在保存的时候,只是保存了attr,并没有保存attrgroup,为了解决这个问题,我们新建了一个vo/AttrVo,在原AttrEntity基础上增加了attrGroupId字段,使得保存新增数据的时候,也保存了它们之间的关系。

通过" BeanUtils.copyProperties(attr,attrEntity);"能够实现在两个Bean之间拷贝数据,但是两个Bean的字段要相同

   @Override
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);
        this.save(attrEntity);
    }

问题:现在有两个查询,一个是查询部分,另外一个是查询全部,但是又必须这样来做吗?还是有必要的,但是可以在后台进行设计,两种查询是根据catId是否为零进行区分的。

2.新建所需vo

每个属性中需要一个attrGroupId,但是数据库中没有对应字段

之前使用@TableField(exist=false)

但是这样在entity中使用不规范,所以使用vo

AttrVo 属性vo对象

gulimall-product/src/main/java/site/zhourui/gulimall/product/vo/AttrVo.java

package site.zhourui.gulimall.product;

import lombok.Data;

/**
 * @author zr
 * @date 2021/10/13 14:04
 */
@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;
}

属性响应vo对象 添加AttrVo的catelogId对应的catelogName与attrGroupId对应的attrGroupName

gulimall-product/src/main/java/site/zhourui/gulimall/product/vo/AttrRespVo.java

package site.zhourui.gulimall.product.vo;

import lombok.Data;

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

    private Long[] catelogPath;
}

属性与属性分组关系vo

gulimall-product/src/main/java/site/zhourui/gulimall/product/vo/AttrGroupRelationVo.java

package site.zhourui.gulimall.product.vo;

import lombok.Data;

@Data
public class AttrGroupRelationVo {

    //"attrId":1,"attrGroupId":2
    private Long attrId;
    private Long attrGroupId;
}

com/atguigu/gulimall/product/vo/AttrGroupWithAttrsVo.java

属性分组带有属性集合的vo

package site.zhourui.gulimall.product.vo;


import lombok.Data;
import site.zhourui.gulimall.product.entity.AttrEntity;

import java.util.List;

@Data
public class AttrGroupWithAttrsVo {

    /**
     * 分组id
     */
    private Long attrGroupId;
    /**
     * 组名
     */
    private String attrGroupName;
    /**
     * 排序
     */
    private Integer sort;
    /**
     * 描述
     */
    private String descript;
    /**
     * 组图标
     */
    private String icon;
    /**
     * 所属分类id
     */
    private Long catelogId;

    private List<AttrEntity> attrs;
}

2.属性分组相关功能接口

谷粒商城--平台属性模块--笔记八

1.AttrService的功能接口

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/AttrService.java 新增接口

	//保存属性接口
    void saveAttr(AttrVo attr);
	//查询基本属性
    PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type);
	//查询属性信息
    AttrRespVo getAttrInfo(Long attrId);
	//更新属性
    void updateAttr(AttrVo attr);
	//获取属性与属性组关系
    List<AttrEntity> getRelationAttr(Long attrgroupId);
	//删除关系
    void deleteRelation(AttrGroupRelationVo[] vos);
	//获取未关联的属性
    PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId);

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/AttrServiceImpl.java 新增实现

 @Transactional
    @Override
	//保存属性接口
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
//        attrEntity.setAttrName(attr.getAttrName());
        BeanUtils.copyProperties(attr,attrEntity);
        //1、保存基本数据
        this.save(attrEntity);
        //2、保存关联关系
        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);
        }


    }
//查询基本属性
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {
        //查询Attr对应的表的attr_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());
		
        //如果分类不是根节点,再加上catelog_id=catelogId的条件
        if(catelogId != 0){
            queryWrapper.eq("catelog_id",catelogId);
        }
		//获取params.key查询条件
        String key = (String) params.get("key");
        //如果key不为空
        if(!StringUtils.isEmpty(key)){
            //attr_id  attr_name
            //加上查询条件,对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();
        //1.对查询结果进行属性赋值将attrEntity转换为attrRespVo
        //2.分库分表查询属性分组的分类名与分组名并赋值到attrRespVo(前提条件属性类型是基础类型)
        // 拿到赋值后的respVos并返回
        List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);

            //1、设置分组的名字
            if("base".equalsIgnoreCase(type)){
                AttrAttrgroupRelationEntity attrId = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
                if (attrId != null && attrId.getAttrGroupId()!=null) {
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrId.getAttrGroupId());
                    attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }

            }

			//2.设置分组名
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                attrRespVo.setCatelogName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());

        pageUtils.setList(respVos);
        return pageUtils;
    }

//根据属性id查询属性信息
    @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));
            if(attrgroupRelation!=null){
                respVo.setAttrGroupId(attrgroupRelation.getAttrGroupId());
                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;
    }
//更新属性
    @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();

            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            relationEntity.setAttrId(attr.getAttrId());
			//查询属性关联表attr_id=attrId的记录数
            Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            //记录数大于0就更新
            if(count>0){

                relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId()));
			//记录数小于等于0就新增
            }else{
                relationDao.insert(relationEntity);
            }
        }


    }

    /**
     * 根据分组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;
    }
	//批量删除属性关联关系
    @Override
    public void deleteRelation(AttrGroupRelationVo[] vos) {
        //relationDao.delete(new QueryWrapper<>().eq("attr_id",1L).eq("attr_group_id",1L));
        //
        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);
    }

    /**
     * 获取当前分组没有关联的所有属性
     * @param params
     * @param attrgroupId
     * @return
     */
    @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));
        List<Long> collect = group.stream().map(item -> {
            return item.getAttrGroupId();
        }).collect(Collectors.toList());

        //2.2)、这些分组关联的属性
        List<AttrAttrgroupRelationEntity> groupId = relationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", collect));
        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;
    }

gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/AttrGroupController.java 新增

	///product/attrgroup/attr/relation
    @PostMapping("/attr/relation")
    public R addRelation(@RequestBody List<AttrGroupRelationVo> vos){

        relationService.saveBatch(vos);
        return R.ok();
    }

    ///product/attrgroup/{catelogId}/withattr
    @GetMapping("/{catelogId}/withattr")
    public R getAttrGroupWithAttrs(@PathVariable("catelogId")Long catelogId){

        //1、查出当前分类下的所有属性分组,
        //2、查出每个属性分组的所有属性
        List<AttrGroupWithAttrsVo> vos =  attrGroupService.getAttrGroupWithAttrsByCatelogId(catelogId);
        return R.ok().put("data",vos);
    }


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

    ///product/attrgroup/{attrgroupId}/noattr/relation
    @GetMapping("/{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);
    }

    @PostMapping("/attr/relation/delete")
    public R deleteRelation(@RequestBody  AttrGroupRelationVo[] vos){
        attrService.deleteRelation(vos);
        return R.ok();
    }

2.根据分类id查出所有的分组以及这些组里面的属性

com/atguigu/gulimall/product/service/AttrGroupService.java

新增根据分类id查出所有的分组以及这些组里面的属性接口

//根据分类id查出所有的分组以及这些组里面的属性
List<AttrGroupWithAttrsVo> getAttrGroupWithAttrsByCatelogId(Long catelogId);

com/atguigu/gulimall/product/service/impl/AttrGroupServiceImpl.java

/**
     * 根据分类id查出所有的分组以及这些组里面的属性
     * @param catelogId
     * @return
     */
    @Override
    public List<AttrGroupWithAttrsVo> getAttrGroupWithAttrsByCatelogId(Long catelogId) {
            //com.atguigu.gulimall.product.vo
        //1、查询分组信息
        List<AttrGroupEntity> attrGroupEntities = this.list(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));

        //2、查询所有属性
        List<AttrGroupWithAttrsVo> collect = attrGroupEntities.stream().map(group -> {
            AttrGroupWithAttrsVo attrsVo = new AttrGroupWithAttrsVo();
            BeanUtils.copyProperties(group,attrsVo);
            List<AttrEntity> attrs = attrService.getRelationAttr(attrsVo.getAttrGroupId());
            attrsVo.setAttrs(attrs);
            return attrsVo;
        }).collect(Collectors.toList());

        return collect;
    }

3.批量保存接口

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/AttrAttrgroupRelationService.java

批量保存接口用vo接数据,逆向工程使用的是entity接的

void saveBatch(List<AttrGroupRelationVo> vos);

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/AttrAttrgroupRelationServiceImpl.java

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

4.批量删除关系接口

gulimall-product/src/main/java/site/zhourui/gulimall/product/dao/AttrAttrgroupRelationDao.java

//批量删除关系接口
void deleteBatchRelation(@Param("entities") List<AttrAttrgroupRelationEntity> entities);

gulimall-product/src/main/resources/mapper/product/AttrAttrgroupRelationDao.xml

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

4.规格参数与销售属性模块

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/ProductAttrValueService.java

新增接口

	//保存产品属性
	void saveProductAttr(List<ProductAttrValueEntity> collect);
	//所属spu的基本属性列表
    List<ProductAttrValueEntity> baseAttrlistforspu(Long spuId);
	//修改所属spu的基本属性
    void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities);

gulimall-product/src/main/java/site/zhourui/gulimall/product/service/impl/ProductAttrValueServiceImpl.java

新增接口实现

   @Override
    public void saveProductAttr(List<ProductAttrValueEntity> collect) {
        this.saveBatch(collect);
    }

    @Override
    public List<ProductAttrValueEntity> baseAttrlistforspu(Long spuId) {
        List<ProductAttrValueEntity> entities = this.baseMapper.selectList(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
        return entities;
    }

    @Transactional
    @Override
    public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
        //1、删除这个spuId之前对应的所有属性
        this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId));


        List<ProductAttrValueEntity> collect = entities.stream().map(item -> {
            item.setSpuId(spuId);
            return item;
        }).collect(Collectors.toList());
        this.saveBatch(collect);
    }

gulimall-product/src/main/java/site/zhourui/gulimall/product/controller/AttrController.java

新增接口方法 新增并修改

@RestController
@RequestMapping("product/attr")
public class AttrController {
    @Autowired
    private AttrService attrService;

    @Autowired
    ProductAttrValueService productAttrValueService;

    ///product/attr/info/{attrId}

    // /product/attr/base/listforspu/{spuId}
    @GetMapping("/base/listforspu/{spuId}")
    public R baseAttrlistforspu(@PathVariable("spuId") Long spuId){

        List<ProductAttrValueEntity> entities = productAttrValueService.baseAttrlistforspu(spuId);

        return R.ok().put("data",entities);
    }

    //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);
    }

    /**
     * 列表
     */
    @RequestMapping("/list")
    //@RequiresPermissions("product:attr:list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = attrService.queryPage(params);

        return R.ok().put("page", page);
    }


    /**
     * 信息
     */
    @RequestMapping("/info/{attrId}")
    //@RequiresPermissions("product:attr:info")
    public R info(@PathVariable("attrId") Long attrId){
        //AttrEntity attr = attrService.getById(attrId);
        AttrRespVo respVo = attrService.getAttrInfo(attrId);

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

    /**
     * 保存
     */
    @RequestMapping("/save")
    //@RequiresPermissions("product:attr:save")
    public R save(@RequestBody AttrVo attr){
        attrService.saveAttr(attr);

        return R.ok();
    }

    ///product/attrgroup/attr/relation/delete


    /**
     * 修改
     */
    @RequestMapping("/update")
    //@RequiresPermissions("product:attr:update")
    public R update(@RequestBody AttrVo attr){
        attrService.updateAttr(attr);

        return R.ok();
    }

    ///product/attr/update/{spuId}
    @PostMapping("/update/{spuId}")
    public R updateSpuAttr(@PathVariable("spuId") Long spuId,
                           @RequestBody List<ProductAttrValueEntity> entities){

        productAttrValueService.updateSpuAttr(spuId,entities);

        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    //@RequiresPermissions("product:attr:delete")
    public R delete(@RequestBody Long[] attrIds){
        attrService.removeByIds(Arrays.asList(attrIds));

        return R.ok();
    }

}

5.前端代码复制

将前端代码全部复制至src/views/modules下

为后续后端开发做准备

谷粒商城--平台属性模块--笔记八

上一篇:DVWA-SQL盲注


下一篇:DVWA——文件上传