谷粒商城–平台属性模块–笔记八
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.品牌分类关联新增接口
原因:电商系统数据量大,少用连表查询,尽量用分库分表查询
逆向工程生成的保存方法只传入了
brandId
和catelogId
并没有传入name所以新增关联后品牌名与分类名为空
解决
修改save方法,根据
brandId
和catelogId
查询出存入品牌名与分类名在存入
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下
为后续后端开发做准备