mybatis自動生成方法介紹(SPU和SKU詳解及MyBatisPlus自動生成)
2023-04-16 09:57:26 6
2-2 SPU和SKU詳解商城系統中的商品信息肯定避免不了SPU和SKU這兩個概念,本節就給大家詳細介紹下這塊的內容
1、掌握SKU和SPU關係SPU = Standard Product Unit (標準化產品單元)
SPU是商品信息聚合的最小單位,是一組可復用、易檢索的標準化信息的集合,該集合描述了一個產品的特性。通俗點講,屬性值、特性相同的商品就可以稱為一個SPU。
SKU=stock keeping unit(庫存量單位)
SKU即庫存進出計量的單位, 可以是以件、盒、託盤等為單位。
SKU是物理上不可分割的最小存貨單元。在使用時要根據不同業態,不同管理模式來處理。在服裝、鞋類商品中使用最多最普遍。
舉個例子:
購買手機的時候,你可以選擇華為Mate40系列手機,Mate40系列手機的生產製造商是華為,品牌是華為,手機分類也是華為,不過Mate40系列手機有多款,比如 Mate40 、Mate40 Pro 、 Mate40 Pro ,每款手機的架構也不一樣,顏色也不一定一樣,那麼這個例子中哪些是Spu哪些是Sku呢?
Spu:
手機系列:Mate40系列廠家:華為品牌:華為分類:手機
Sku:
價格顏色網絡格式
spu:
CREATE TABLE `spu` ( `id` varchar(60) NOT NULL COMMENT '主鍵', `name` varchar(100) DEFAULT NULL COMMENT 'SPU名', `intro` varchar(200) DEFAULT NULL COMMENT '簡介', `brand_id` int(11) DEFAULT NULL COMMENT '品牌ID', `category_one_id` int(20) DEFAULT NULL COMMENT '一級分類', `category_two_id` int(10) DEFAULT NULL COMMENT '二級分類', `category_three_id` int(10) DEFAULT NULL COMMENT '三級分類', `images` varchar(1000) DEFAULT NULL COMMENT '圖片列表', `after_sales_Service` varchar(50) DEFAULT NULL COMMENT '售後服務', `content` longtext COMMENT '介紹', `attribute_list` varchar(3000) DEFAULT NULL COMMENT '規格列表', `is_marketable` int(1) DEFAULT '0' COMMENT '是否上架,0已下架,1已上架', `is_delete` int(1) DEFAULT '0' COMMENT '是否刪除,0:未刪除,1:已刪除', `status` int(1) DEFAULT '0' COMMENT '審核狀態,0:未審核,1:已審核,2:審核不通過', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
sku:
CREATE TABLE `sku` ( `id` varchar(60) NOT NULL COMMENT '商品id', `name` varchar(200) NOT NULL COMMENT 'SKU名稱', `price` int(20) NOT NULL DEFAULT '1' COMMENT '價格(分)', `num` int(10) DEFAULT '100' COMMENT '庫存數量', `image` varchar(200) DEFAULT NULL COMMENT '商品圖片', `images` varchar(2000) DEFAULT NULL COMMENT '商品圖片列表', `create_time` datetime DEFAULT NULL COMMENT '創建時間', `update_time` datetime DEFAULT NULL COMMENT '更新時間', `spu_id` varchar(60) DEFAULT NULL COMMENT 'SPUID', `category_id` int(10) DEFAULT NULL COMMENT '類目ID', `category_name` varchar(200) DEFAULT NULL COMMENT '類目名稱', `Brand_id` int(11) DEFAULT NULL COMMENT '品牌id', `brand_name` varchar(100) DEFAULT NULL COMMENT '品牌名稱', `sku_attribute` varchar(200) DEFAULT NULL COMMENT '規格', `status` int(1) DEFAULT '1' COMMENT '商品狀態 1-正常,2-下架,3-刪除', PRIMARY KEY (`id`), KEY `cid` (`category_id`), KEY `status` (`status`), KEY `updated` (`update_time`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';
2.2 商品發布流程分析商品發布流程如下:
1)分類選擇
發布商品前,需要先選擇發布商品所屬分類,分類嚴格定義為3級分類。
分類表:
CREATE TABLE `category` ( `id` int(20) NOT NULL AUTO_INCREMENT COMMENT '分類ID', `name` varchar(50) DEFAULT NULL COMMENT '分類名稱', `sort` int(11) DEFAULT NULL COMMENT '排序', `parent_id` int(20) DEFAULT NULL COMMENT '上級ID', PRIMARY KEY (`id`), KEY `parent_id` (`parent_id`)) ENGINE=InnoDB AUTO_INCREMENT=11182 DEFAULT CHARSET=utf8 COMMENT='商品類目';
2)選擇品牌
分類選擇完成後,需要加載品牌,品牌加載並非一次性加載完成,而是根據選擇的分類進行加載。
分類品牌關係表:
CREATE TABLE `category_brand` ( `category_id` int(11) NOT NULL COMMENT '分類ID', `brand_id` int(11) NOT NULL COMMENT '品牌ID', PRIMARY KEY (`brand_id`,`category_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
品牌表:
CREATE TABLE `brand` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '品牌id', `name` varchar(100) NOT NULL COMMENT '品牌名稱', `image` varchar(1000) DEFAULT '' COMMENT '品牌圖片地址', `initial` varchar(1) DEFAULT '' COMMENT '品牌的首字母', `sort` int(11) DEFAULT NULL COMMENT '排序', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='品牌表';
3)屬性加載
當選擇分類後,加載分類對應的屬性。
分類屬性表:
CREATE TABLE `category_attr` ( `category_id` int(11) NOT NULL, `attr_id` int(11) NOT NULL COMMENT '屬性分類表', PRIMARY KEY (`category_id`,`attr_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
屬性表:
CREATE TABLE `sku_attribute` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(50) DEFAULT NULL COMMENT '屬性名稱', `options` varchar(2000) DEFAULT NULL COMMENT '屬性選項', `sort` int(11) DEFAULT NULL COMMENT '排序', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
3、 商品發布加載功能對應的Bean我們已經提前寫好,如下
package com.bobo.vip.mall.goods.model;import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;/***** * @Author: 波波 * @Description: 雲商城 ****/@Data@AllArgsConstructor@NoArgsConstructor//MyBatisPlus表映射註解@TableName(value = "category")public class Category implements Serializable { @TableId(type = IdType.AUTO) private Integer id; private String name; private Integer sort; private Integer parentId;}
package com.bobo.vip.mall.goods.model;import com.baomidou.mybatisplus.annotation.TableField;import com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;/***** * @Author: 波波 * @Description: 雲商城 ****/@Data@AllArgsConstructor@NoArgsConstructor//MyBatisPlus表映射註解@TableName(value = "category_attr")public class CategoryAttr { @TableField private Integer categoryId; @TableField private Integer attrId;}
/***** * @Author: 波波 * @Description: 雲商城 ****/@Data@AllArgsConstructor@NoArgsConstructor//MyBatisPlus表映射註解@TableName(value = "category_brand")public class CategoryBrand { @TableField private Integer categoryId; @TableField private Integer brandId;}
/***** * @Author: 波波 * @Description: 雲商城 ****/@Data@NoArgsConstructor@AllArgsConstructorpublic class Product { // Spu private Spu spu; // Sku private List skus;}1234567891011121314
@Data@AllArgsConstructor@NoArgsConstructor//MyBatisPlus表映射註解@TableName(value = "sku")public class Sku { @TableId(type = IdType.ASSIGN_ID) private String id; private String name; private Integer price; private Integer num; private String image; private String images; private Date createTime; private Date updateTime; private String spuId; private Integer categoryId; private String categoryName; private Integer brandId; private String brandName; private String skuAttribute; private Integer status;}
/***** * @Author: 波波 * @Description: 雲商城 ****/@Data@AllArgsConstructor@NoArgsConstructor//MyBatisPlus表映射註解@TableName(value = "sku_attribute")public class SkuAttribute implements Serializable { @TableId(type = IdType.AUTO) private Integer id; private String name; private String options; private Integer sort; //對應分類 @TableField(exist = false) private List categories;}12345678910111213141516171819202122
@Data@AllArgsConstructor@NoArgsConstructor//MyBatisPlus表映射註解@TableName(value = "spu")public class Spu { @TableId(type = IdType.ASSIGN_ID) private String id; private String name; private String intro; private Integer brandId; private Integer categoryOneId; private Integer categoryTwoId; private Integer categoryThreeId; private String images; private String afterSalesservice; private String content; private String attributeList; private Integer isMarketable; private Integer isDelete; private Integer status;}
3.1 分類加載分類功能需要實現按照父ID查詢,最開始初始化加載的是頂級父類,parent_id=0,後面每次點擊的時候都根據傳入的id查詢子分類。
1)Mapper
創建com.bobo.vip.mall.goods.mapper.CategoryMapper,代碼如下:
public interface CategoryMapper extends BaseMapper {}12
2)Service
接口:com.bobo.vip.mall.goods.service.CategoryService代碼如下:
public interface CategoryService extends IService { /** * 根據父ID查詢子分類 * @param pid * @return */ List queryByParentId(Integer pid);}123456789
實現類:com.bobo.vip.mall.goods.service.impl.CategoryServiceImpl代碼如下:
@Servicepublic class CategoryServiceImpl extends ServiceImpl implements CategoryService { @Autowired private CategoryMapper categoryMapper; /*** * 根據父ID查詢子分類 * @param pid * @return */ @Override public List queryByParentId(Integer pid) { //條件封裝 QueryWrapper queryWrapper = new QueryWrapper; queryWrapper.eq("parent_id",pid); return categoryMapper.selectList(queryWrapper); }}12345678910111213141516171819
3)Controller
創建com.bobo.vip.mall.goods.controller.CategoryController代碼如下;
@RestController@RequestMapping(value = "/category")@CrossOriginpublic class CategoryController { @Autowired private CategoryService categoryService; /**** * 根據父ID查詢子分類 */ @GetMapping(value = "/parent/{pid}") public RespResult<List> list(@PathVariable(value = "pid")Integer pid){ List categories = categoryService.queryByParentId(pid); return RespResult.ok(categories); }}1234567891011121314151617
3.2 品牌加載品牌需要根據分類進行加載,當用戶選擇第3級分類的時候,加載品牌,品牌數據需要經過category_brand表關聯查詢。
我們可以按照如下步驟實現:
1、查詢category_brand中指定分類對應的品牌ID集合2、從brand查出品牌集合
1)Mapper
修改com.bobo.vip.mall.goods.mapper.BrandMapper,添加根據分類ID查詢品牌ID集合:
//根據分類ID查詢品牌集合@Select("select brand_id from category_brand where category_id=#{id}")List queryBrandIds(Integer id);123
2)Service
接口:com.bobo.vip.mall.goods.service.BrandService中添加根據分類ID查詢品牌集合方法
//根據分類ID查詢品牌List queryByCategoryId(Integer id);12
實現類:com.bobo.vip.mall.goods.service.impl.BrandServiceImpl
/*** * 根據分類ID查詢品牌 * @param id * @return */@Overridepublic List queryByCategoryId(Integer id) { //查詢分類ID對應的品牌集合 List brandIds = brandMapper.queryBrandIds(id); //根據品牌ID集合查詢品牌信息 List brands = brandMapper.selectBatchIds(brandIds); return brands;}12345678910111213
3)Controller
修改com.bobo.vip.mall.goods.controller.BrandController添加根據分類ID查詢品牌集合
/**** * 根據分類ID查詢品牌 */@GetMapping(value = "/category/{id}")public RespResult<List> categoryBrands(@PathVariable(value = "id")Integer id){ List brands = brandService.queryByCategoryId(id); return RespResult.ok(brands);}12345678
屬性也稱為規格,屬性也需要根據分類查詢,我們可以按照如下思路實現:
1、先從category_attr根據分類ID查詢出當前分類擁有的屬性ID集合2、從sku_attribute中查詢屬性集合
1)Mapper
創建com.bobo.vip.mall.goods.mapper.SkuAttributeMapper實現根據分類ID查詢屬性信息。
/*** * 根據分類ID查詢屬性集合 * @param id * @return */@Select("SELECT * FROM sku_attribute WHERE id IN(SELECT attr_id FROM category_attr WHERE category_id=#{id})")List queryByCategoryId(Integer id);1234567
2)Service
接口:com.bobo.vip.mall.goods.service.SkuAttributeService添加根據分類ID查詢屬性集合方法
//根據分類ID查詢屬性集合List queryList(Integer id);12
實現類:com.bobo.vip.mall.goods.service.impl.SkuAttributeServiceImpl添加如下實現方法
/*** * 根據分類ID查詢屬性集合 * @param id * @return */@Overridepublic List queryList(Integer id) { return skuAttributeMapper.queryByCategoryId(id);}123456789
3)Controller
創建com.bobo.vip.mall.goods.controller.SkuAttributeController,添加如下方法
/*** * 根據分類ID查詢 */@GetMapping(value = "/category/{id}")public RespResult categoryAttributeList(@PathVariable(value = "id")Integer id){ //根據分類ID查詢屬性參數 List skuAttributes = skuAttributeService.queryList(id); return RespResult.ok(skuAttributes);}123456789
4、商品發布4.1 複合對象分析商品發布,如上圖,我們可以發現發布的商品信息包含Sku和Spu,因此我們應該在後端能有一個對象同時能接到Spu和多個Sku,方法有很多種,我們可以直接在Spu中寫一個List,但這種方法不推薦,按照對象設計原則,對一個對象進行擴展時,儘量避免對原始對象造成改變,因此我們可以使用複合類,可以創建一個Prodcut類,該類中有Spu也有List,代碼如下:
@Data@NoArgsConstructor@AllArgsConstructorpublic class Product { // Spu private Spu spu; // Sku private List skus;}123456789
4.2 添加商品添加商品的時候,我們需要保存Spu,同時需要添加多個Sku。我們可以在華為商城中看看真實電商中Sku名字特徵,每次點擊不同屬性的時候,前部分名字一樣,只是將名字中的規格替換了,也就是說Sku的名字其實是組合成的,一部分是Spu的一部分是Sku的,可以進行組合。
1)名字分析
添加商品的時候,會將商品的屬性傳入後臺,格式如下,如果把規格名字添加到名字中,那就是華為商城中的效果了,我們可以這麼做,把屬性解析成Map,然後每個屬性值添加到商品名字中即可。
{"適合人群":"有一定java基礎的人","書籍分類":"軟體編程"}
2)實現代碼
Mapper
com.bobo.vip.mall.goods.mapper.SpuMapper代碼如下:
public interface SpuMapper extends BaseMapper {}12
com.bobo.vip.mall.goods.mapper.SkuMapper代碼如下:
public interface SkuMapper extends BaseMapper {}12
Service
com.bobo.vip.mall.goods.service.SpuService中添加產品方法如下
public interface SpuService extends IService { //保存商品 void saveProduct(Product product);}1234
com.bobo.vip.mall.goods.service.impl.SpuServiceImpl中添加產品方法如下:
@Servicepublic class SpuServiceImpl extends ServiceImpl implements SpuService { @Autowired private SkuMapper skuMapper; @Autowired private SpuMapper spuMapper; @Autowired private CategoryMapper categoryMapper; @Autowired private BrandMapper brandMapper; // 保存商品 @Override public void saveProduct(Product product) { //Spu Spu spu = product.getSpu; //上架 spu.setIsMarketable(1); //未刪除 spu.setIsDelete(0); //狀態 spu.setStatus(1); //添加 spuMapper.insert(spu); //查詢三級分類 Category category = categoryMapper.selectById(spu.getCategoryThreeId); //查詢品牌 Brand brand = brandMapper.selectById(spu.getBrandId); //當前時間 Date now = new Date; //新增Sku集合 for (Sku sku : product.getSkus) { //設置名字 String skuName = spu.getName; Map attrMap = JSON.parseObject(sku.getSkuAttribute, Map.class); for (Map.Entry entry : attrMap.entrySet) { skuName = " " entry.getValue; } sku.setName(skuName); //設置圖片 sku.setImages(spu.getImages); //設置狀態 sku.setStatus(1); //設置類目ID sku.setCategoryId(spu.getCategoryThreeId); //設置類目名稱 sku.setCategoryName(category.getName); //設置品牌ID sku.setBrandId(brand.getId); //設置品牌名稱 sku.setBrandName(brand.getName); //設置Spuid sku.setSpuId(spu.getId); //時間 sku.setCreateTime(now); sku.setUpdateTime(now); //增加 skuMapper.insert(sku); } }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
Controller
創建com.bobo.vip.mall.goods.controller.SpuController,添加產品代碼如下:
@Autowiredprivate SpuService spuService;/*** * 保存 */@PostMapping(value = "/save")public RespResult save(@RequestBody Product product){ //保存 spuService.saveProduct(product); return RespResult.ok;}
4.3 產品修改產品修改其實和產品添加幾乎一致,只需要做小改動即可,實現步驟如下:
1、如果Spu的id值不為空,說明是修改操作2、如果是修改操作,先刪除之前對應的Sku集合3、其他流程和添加商品一致
修改com.bobo.vip.mall.goods.service.impl.SpuServiceImpl的save方法,代碼如下:
在這裡插入圖片描述
源碼如下:
@Overridepublic void saveProduct(Product product) { //Spu Spu spu = product.getSpu; //如果ID為空,則增加 if(StringUtils.isEmpty(spu.getId)){ //上架 spu.setIsMarketable(1); //未刪除 spu.setIsDelete(0); //狀態 spu.setStatus(1); //添加 spuMapper.insert(spu); }else{ //ID 不為空,則修改 spuMapper.updateById(spu); //刪除之前的Sku記錄 skuMapper.delete(new QueryWrapper.eq("spu_id",spu.getId)); } //查詢三級分類 Category category = categoryMapper.selectById(spu.getCategoryThreeId); //查詢品牌 Brand brand = brandMapper.selectById(spu.getBrandId); //當前時間 Date now = new Date; //新增Sku集合 for (Sku sku : product.getSkus) { //設置名字 String skuName = spu.getName; Map attrMap = JSON.parseObject(sku.getSkuAttribute, Map.class); for (Map.Entry entry : attrMap.entrySet) { skuName = " " entry.getValue; } sku.setName(skuName); //設置圖片 sku.setImages(spu.getImages); //設置狀態 sku.setStatus(1); //設置類目ID sku.setCategoryId(spu.getCategoryThreeId); //設置類目名稱 sku.setCategoryName(category.getName); //設置品牌ID sku.setBrandId(brand.getId); //設置品牌名稱 sku.setBrandName(brand.getName); //設置Spuid sku.setSpuId(spu.getId); //時間 sku.setCreateTime(now); sku.setUpdateTime(now); //增加 skuMapper.insert(sku); }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
5 MyBatis Plus代碼生成我們可以發現個問題,剛才寫的很多增刪改查代碼都比較簡單,比較枯燥,重複寫一些類的創建、單表增刪改查非常類,而創建對象和單標操作的代碼,在開發中幾乎佔用了開發時間的80%,如果能夠用工具生成就可以大大節省我們開發成本了。
5.1 MyBatis Plus介紹AutoGenerator 是 MyBatis-Plus 的代碼生成器,通過 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各個模塊的代碼,極大的提升了開發效率。
學習網址 https://baomidou.com/guide/generator.html
5.2 MyBatisPlus代碼生成配置1)引入依賴
com.baomidou mybatis-plus-generator 3.4.0 org.apache.velocity velocity-engine-core 2.21234567891011
2)代碼生成
public static void main(String[] args) { // 代碼生成器 AutoGenerator mpg = new AutoGenerator; // 全局配置 GlobalConfig gc = new GlobalConfig; String projectPath = System.getProperty("user.dir"); gc.setOutputDir(projectPath "/src/main/java"); // 文件輸出路徑 gc.setAuthor("bobo"); //作者 gc.setOpen(false); //生成之後是否打開目錄 gc.setIdType(IdType.NONE); //主鍵策略 gc.setServiceName("%sService"); //名字設置 %s是佔位符,可以理解成類的名字 mpg.setGlobalConfig(gc); // 數據源配置 DataSourceConfig dsc = new DataSourceConfig; dsc.setUrl("jdbc:mysql://192.168.100.140:3306/shop_goods?useUnicode=true&useSSL=false&characterEncoding=utf8"); dsc.setDriverName("com.mysql.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("123456"); mpg.setDataSource(dsc); // 包配置 PackageConfig pc = new PackageConfig; pc.setModuleName("mall-goods"); pc.setParent("com.bobo.code"); mpg.setPackageInfo(pc); // 策略配置 StrategyConfig strategy = new StrategyConfig; strategy.setNaming(NamingStrategy.underline_to_camel); //駝峰命名 strategy.setColumnNaming(NamingStrategy.underline_to_camel); //駝峰命名 strategy.setEntityLombokModel(true); //是否使用Lombok strategy.setRestControllerStyle(true); //是否生成RestController // 寫於父類中的公共欄位 strategy.setSuperEntityColumns("id"); //公共欄位定義 strategy.setControllerMappingHyphenStyle(true); //駝峰轉連字符 strategy.setTablePrefix(pc.getModuleName "_"); //表前綴 mpg.setStrategy(strategy); mpg.execute;}
效果
有紅色的提示是因為沒有引入依賴,我們可以把生成的相關內容拷貝到合適的項目位置即可。
,