MapStruct
简单使用,都说它的性能高,这里主要用来替代
BeanUtils.copyProperties()
注意
一旦MapStruct
配置文件报错,修改之后,需要重新编译
选择配置文件所在的模块,然后Rebuild
导入依赖
如果项目中使用lombok,需要先与lombok进行版本匹配,否则编译后的实现类里面,可能会出现没有对属性进行 set 的情况
<!--mapstruct-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
创建接口
package com.indi.gulimall.product.mapstuct;
@Mapper(componentModel = "spring")
public interface ProductCovertBasic {
ProductCovertBasic INSTANCE = Mappers.getMapper(ProductCovertBasic.class);
AttrEntity toAttr(AttrVO attrVO);
}
调用
// 将VO转换成Entity
AttrEntity attr = ProductCovertBasic.INSTANCE.attrVOToAttr(attrVO);
销售属性设置
为了使销售属性与基本属性共用一套逻辑,数据库中有一个属性类型的字段,只需在处理具体逻辑时,判断属性类型即可,为了方便管理属性类型的值,我们将其存放到枚举中。
后端
通用模块,添加基本属性与销售属性的枚举
package com.indi.common.constant;
public class ProductConstant {
@Getter
@AllArgsConstructor
public enum AttrEnum{
ATTR_TYPE_SALE(0,"销售属性"),
ATTR_TYPE_BASE(1,"基本属性");
private int code;
private String message;
}
}
新增规格参数
需求
后端
AttrVO
package com.indi.gulimall.product.vo;
@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 categoryId;
/**
* 快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整
*/
private Integer showDesc;
/**
* 属性分组id
*/
private Long attrGroupId;
}
AdminAttrController
/**
* 保存
*/
@RequestMapping("/save")
public R save(@RequestBody AttrVO attrVO){
attrService.saveAttr(attrVO);
return R.ok();
}
AttrService
void saveAttr(AttrVO attrVO);
AttrServiceImpl
@Transactional
@Override
public void saveAttr(AttrVO attrVO) {
// 保存基本数据
AttrEntity attr = ProductCovertBasic.INSTANCE.attrVOToAttr(attrVO);
this.save(attr);
if (attr.getAttrType() == AttrEnum.ATTR_TYPE_BASE.getCode()) {
// 保存关联关系
AttrAttrGroupRelationEntity relation = new AttrAttrGroupRelationEntity();
relation.setAttrGroupId(attrVO.getAttrGroupId());
relation.setAttrId(attr.getAttrId());
relationDao.insert(relation);
}
}
查询规格参数
需求
后端
AttrRespVO
package com.indi.gulimall.product.vo;
@Data
public class AttrRespVO extends AttrVO{
private String categoryName;
private String groupName;
}
ProductCovertBasic
转换工具类
如果改过类名的话,需要删除class文件,重新编译
AttrRespVO attrToAttrRespVO(AttrEntity attr);
AdminAttrController
/**
* 列表
*/
@GetMapping("/{attrType}/list/{categoryId}")
public R list(@RequestParam Map<String, Object> params,
@PathVariable Long categoryId,
@PathVariable String attrType) {
PageUtils page = attrService.queryBaseAttrPage(params, categoryId, attrType);
return R.ok().put("page", page);
}
AttrService
PageUtils queryBaseAttrPage(Map<String, Object> params, Long categoryId);
AttrServiceImpl
@Resource
private CategoryDao categoryDao;
@Resource
private AttrGroupDao attrGroupDao;
@Override
public PageUtils queryBaseAttrPage(Map<String, Object> params, Long categoryId) {
QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("attr_type",
"base".equalsIgnoreCase(attrType)
? AttrEnum.ATTR_TYPE_BASE.getCode()
: AttrEnum.ATTR_TYPE_SALE.getCode()
);
String key = (String) params.get("key");
if (categoryId != 0) {
queryWrapper.eq("category_id", categoryId);
}
if (StringUtils.isNotEmpty(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> recordList = page.getRecords();
List<AttrRespVO> attrRespVOList = recordList.stream().map(attr -> {
AttrRespVO attrRespVO = ProductCovertBasic.INSTANCE.attrToAttrRespVO(attr);
// 设置分类名称
CategoryEntity category = categoryDao.selectById(attr.getCategoryId());
if (category != null) {
attrRespVO.setCategoryName(category.getName());
}
if ("base".equalsIgnoreCase(attrType)) {
// 先查分组id
QueryWrapper<AttrAttrGroupRelationEntity> relationWrapper = new QueryWrapper<>();
relationWrapper.eq("attr_id", attr.getAttrId());
AttrAttrGroupRelationEntity relation = relationDao.selectOne(relationWrapper);
// 再根据分组id查分组名称
if (relation != null && relation.getAttrGroupId() != null) {
AttrGroupEntity attrGroup = attrGroupDao.selectById(relation.getAttrGroupId());
if (attrGroup != null) {
attrRespVO.setGroupName(attrGroup.getAttrGroupName());
}
}
}
return attrRespVO;
}).collect(Collectors.toList());
pageUtils.setList(attrRespVOList);
return pageUtils;
}
回显规格参数
需求
点击修改时,回显规格参数、分类信息、分组信息
后端
AttrRespVO
private Long[] categoryPath;
AdminAttrController
/**
* 信息
*/
@GetMapping("/info/{attrId}")
public R info(@PathVariable("attrId") Long attrId) {
AttrEntity attr = attrService.getById(attrId);
AttrRespVO attrRespVO = attrService.getAttrInfo(attrId);
return R.ok().put("attr", attrRespVO);
}
AttrService
AttrRespVO getAttrInfo(Long attrId);
AttrServiceImpl
@Resource
private CategoryService categoryService;
@Override
public AttrRespVO getAttrInfo(Long attrId) {
AttrEntity attr = this.getById(attrId);
AttrRespVO attrRespVO = ProductCovertBasic.INSTANCE.attrToAttrRespVO(attr);
if (attr.getAttrType() == AttrEnum.ATTR_TYPE_BASE.getCode()) {
// 设置分组id、分组名称
AttrAttrGroupRelationEntity relation = relationDao.selectOne(
new QueryWrapper<AttrAttrGroupRelationEntity>().eq("attr_id", attrId)
);
if (relation != null) {
attrRespVO.setAttrGroupId(relation.getAttrGroupId());
AttrGroupEntity attrGroup = attrGroupDao.selectById(relation.getAttrGroupId());
if (attrGroup != null) {
attrRespVO.setGroupName(attrGroup.getAttrGroupName());
}
}
}
// 设置分类的完整路径、分类名称
Long[] categoryPath = categoryService.findCategoryPath(attr.getCategoryId());
attrRespVO.setCategoryPath(categoryPath);
CategoryEntity category = categoryDao.selectById(attr.getCategoryId());
if (category != null) {
attrRespVO.setCategoryName(category.getName());
}
return attrRespVO;
}
更新规格参数
后端
AdminAttrController
/**
* 修改
*/
@PostMapping("/update")
public R update(@RequestBody AttrVO attrVO) {
attrService.updateAttr(attrVO);
return R.ok();
}
AttrService
void updateAttr(AttrVO attrVO);
AttrServiceImpl
@Override
public void updateAttr(AttrVO attrVO) {
AttrEntity attr = ProductCovertBasic.INSTANCE.attrVOToAttr(attrVO);
this.updateById(attr);
if (attr.getAttrType() == AttrEnum.ATTR_TYPE_BASE.getCode()) {
// 根据分组关联是否存在决定,新增/修改分组关联
AttrAttrGroupRelationEntity relation = new AttrAttrGroupRelationEntity();
Integer count = relationDao.selectCount(
new QueryWrapper<AttrAttrGroupRelationEntity>().eq("attr_id", attrVO.getAttrId())
);
if (count > 0) {
// 更改分类的时候,可能会导致分组id清空,需要做空值判断
relationDao.update(
relation,
new UpdateWrapper<AttrAttrGroupRelationEntity>()
.eq("attr_id", attrVO.getAttrId())
.set("attr_group_id", attrVO.getAttrGroupId() == null ? null : attrVO.getAttrGroupId())
);
} else {
relation.setAttrGroupId(attrVO.getAttrGroupId());
relation.setAttrId(attrVO.getAttrId());
relationDao.insert(relation);
}
}
}