文章目录
- 一、表结构介绍
- 二、列表查询
- 三、添加功能(复杂)
- 3.1 加载品牌数据
- 3.2 加载商品单元数据
- 3.3 加载商品规格数据
- 3.4 保存商品数据
- 四、修改功能
- 4.1 查询商品详情
- 4.2 保存修改数据
- 五、删除商品
- 六、商品审核
- 七、商品上下架
一、表结构介绍
商品管理就是对电商项目中所涉及到的商品数据进行维护,其所对应的表结构如下所示:
CREATE TABLE `product` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '商品名称',
`brand_id` bigint DEFAULT NULL COMMENT '品牌ID',
`category1_id` bigint DEFAULT NULL COMMENT '一级分类id',
`category2_id` bigint DEFAULT NULL COMMENT '二级分类id',
`category3_id` bigint DEFAULT NULL COMMENT '三级分类id',
`unit_name` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '计量单位',
`slider_urls` text COMMENT '轮播图',
`spec_value` varchar(255) DEFAULT NULL COMMENT '商品规格json',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '线上状态:0-初始值,1-上架,-1-自主下架',
`audit_status` tinyint NOT NULL DEFAULT '0' COMMENT '审核状态:0-初始值,1-通过,-1-未通过',
`audit_message` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '审核信息',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '删除标记(0:可用 1:不可用)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品'
二、列表查询
需求说明:
如果在搜索表单中选择了某一个品牌以及分类,那么此时就需要按照品牌id和分类id进行查询;搜索的时候需要进行分页搜索。前端进行参数传递的时候,不一定会传递搜索条件,因此sql语句的编写需要使用到动态sql
debug到controller层,可以看到拿到了品牌id值2,对应的就是品牌华为
在业务层进行分页查询,通过查询结果可知,只查询到了一条数据。并且返回了商品名称、二级、三级分类名称等信息
SQL复杂在多表查询,因为要查询一级、二级、三级分类,所以有些复杂,SQL代码如下:
<!-- List<Product> findByPage(ProductDto productDto);-->
<select id="findByPage" resultType="com.atguigu.spzx.model.entity.product.Product">
select
p.id, p.name , p.brand_id , p.category1_id , p.category2_id , p.category3_id, p.unit_name,
p.slider_urls , p.spec_value , p.status , p.audit_status , p.audit_message , p.create_time , p.update_time ,
p.is_deleted ,
b.name brandName , c1.name category1Name , c2.name category2Name , c3.name category3Name
from product p
LEFT JOIN brand b on b.id = p.brand_id
LEFT JOIN category c1 on c1.id = p.category1_id
LEFT JOIN category c2 on c2.id = p.category2_id
LEFT JOIN category c3 on c3.id = p.category3_id
<where>
p.is_deleted = 0
<if test="brandId != null and brandId != ''">
and p.brand_id = #{brandId}
</if>
<if test="category1Id != null and category1Id != ''">
and p.category1_id = #{category1Id}
</if>
<if test="category2Id != null and category2Id != ''">
and p.category2_id = #{category2Id}
</if>
<if test="category3Id != null and category3Id != ''">
and p.category3_id = #{category3Id}
</if>
</where>
order by id desc
</select>
三、添加功能(复杂)
需求说明:
当用户点击添加按钮的时候,在对话框中需要展示添加商品的表单。当用户在该表单中点击提交按钮的时候那么此时就需要将表单进行提交,在后端需要将提交过来的表单数据保存到数据库中。通过业务分析,我们需要在添加功能中完成四个接口:加载品牌数据接口、加载商品单元数据接口、加载商品规格数据接口、保存商品数据接口。接下来让我们一个一个完成接口的需求分析和debug分析。
3.1 加载品牌数据
需求: 当用户选择了三级分类以后,此时需要将三级分类所对应的品牌数据查询出来,并在品牌下拉框中进行展示
这个接口还是比较简单的,来到controller层,获取到分类id值694
业务层调用分类品牌表mapper接口,查询到品牌数据,放到list接口中
对应的SQL如下,这里设计到两表查询
<!-- List<Brand> findBrandByCategoryId(Long categoryId);-->
<select id="findBrandByCategoryId" resultType="com.atguigu.spzx.model.entity.product.Brand">
select b.*
from category_brand cb
left join brand b
on b.id = cb.brand_id
where cb.category_id = #{categoryId} and b.is_deleted = 0
order by cb.id desc
</select>
3.2 加载商品单元数据
需求: 当添加商品的表单对话框展示出来以后,此时就需要从数据库中查询出来所有的商品单元数据,并将查询到的商品单元数据在商品单元下拉框中进行展示。
这个接口也很简单,就是查询所有数据的操作。
SQL代码编写如下:
@Select("select * from product_unit where is_deleted = 0 order by id")
List<ProductUnit> findAll();
3.3 加载商品规格数据
需求: 当添加商品的表单对话框展示出来以后,此时就需要从数据库中查询出来所有的商品规格数据,并将查询到的商品规格数据在商品规格下拉框中进行展示。
controller层代码如下:
这里是业务层代码:
SQL语句如下:
@Select("select * from product_spec where is_deleted = 0 order by id")
List<ProductSpec> findAll();
3.4 保存商品数据
这个接口比较复杂,思路分析:
- 前端提交过来的数据,包含了SPU的基本数据,SKU的列表数据,商品详情数据
后端可以直接使用Product接收请求参数,但是需要扩展对应的属性
保存数据的时候需要操作三张表: product、product_sku、product_detail
添加测试信息如下图:
提交表格,debug到controller层,可以看到提交过来的参数信息
业务层首先是保存商品数据
接着保存商品sku数据
最后保存商品详情数据
这里的SQL语句不是很难,三个SQL语句代码如下:
<!-- void save(Product product);-->
<insert id="save">
insert into product
values (#{id}, #{name}, #{brandId}, #{category1Id}, #{category2Id}, #{category3Id}, #{unitName},
#{sliderUrls}, #{specValue}, #{status}, #{auditStatus}, #{auditMessage}, now(), now(), 0)
</insert>
<!-- void save(ProductSku productSku);-->
<insert id="save">
insert into product_sku
values (#{id}, #{skuCode}, #{skuName}, #{productId}, #{thumbImg}, #{salePrice}, #{marketPrice}, #{costPrice},
#{stockNum}, #{saleNum}, #{skuSpec}, #{weight}, #{volume}, #{status}, now(), now(), 0)
</insert>
<!-- void save(ProductDetails productDetails);-->
<insert id="save">
insert into product_details
values (#{id}, #{productId}, #{imageUrls}, now(), now(), 0)
</insert>
四、修改功能
需求分析: 当用户点击修改按钮的时候,那么此时就弹出对话框,在该对话框的商品表单中回显商品相关数据,此时用户对商品数据进行修改,修改完毕以后点击提交按钮将表单进行提交,后端服务修改数据库中数据即可。这里的业务处理思路跟添加商品类似,主要是SQL语句编写的区别。涉及到两个接口:查询商品详情接口、保存修改数据接口。
4.1 查询商品详情
controller层获取到要修改商品的id值
业务层涉及到三个查询语句:根据id查询商品数据、根据商品的id查询sku数据、根据商品的id查询商品详情数据,最后返回数据。
查询数据的三个SQL语句编写如下,难度不大。
<!--Product selectById(Long id);-->
<select id="selectById" resultType="com.atguigu.spzx.model.entity.product.Product">
select p.id,
p.name,
p.brand_id,
p.category1_id,
p.category2_id,
p.category3_id,
p.unit_name,
p.slider_urls,
p.spec_value,
p.status,
p.audit_status,
p.audit_message,
p.create_time,
p.update_time,
p.is_deleted,
b.name brandName,
c1.name category1Name,
c2.name category2Name,
c2.name category3Name
from product p
LEFT JOIN brand b on b.id = p.brand_id
LEFT JOIN category c1 on c1.id = p.category1_id
LEFT JOIN category c2 on c2.id = p.category2_id
LEFT JOIN category c3 on c3.id = p.category3_id
where p.id = #{id}
and p.is_deleted = 0
</select>
<!-- List<ProductSku> selectByProductId(Long id);-->
<select id="selectByProductId" resultType="com.atguigu.spzx.model.entity.product.ProductSku">
select *
from product_sku
where product_id = #{productId}
and is_deleted = 0
order by id desc
</select>
<!-- ProductDetails selectByProductId(Long id);-->
<select id="selectByProductId" resultType="com.atguigu.spzx.model.entity.product.ProductDetails">
select *
from product_details
where product_id = #{productId}
and is_deleted = 0
</select>
4.2 保存修改数据
controller层用来接收表单数据
业务层逻辑与查询一致
修改的三个SQL语句看着多,其实不难的
<!-- void updateById(Product product);-->
<update id="updateById">
update product set
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="brandId != null and brandId != ''">
brand_id = #{brandId},
</if>
<if test="category1Id != null and category1Id != ''">
category1_id = #{category1Id},
</if>
<if test="category2Id != null and category2Id != ''">
category2_id = #{category2Id},
</if>
<if test="category3Id != null and category3Id != ''">
category3_id = #{category3Id},
</if>
<if test="unitName != null and unitName != ''">
unit_name = #{unitName},
</if>
<if test="sliderUrls != null and sliderUrls != ''">
slider_urls = #{sliderUrls},
</if>
<if test="specValue != null and specValue != ''">
spec_value = #{specValue},
</if>
<if test="status != null and status != ''">
status = #{status},
</if>
<if test="auditStatus != null and auditStatus != ''">
audit_status = #{auditStatus},
</if>
<if test="auditMessage != null and auditMessage != ''">
audit_message = #{auditMessage},
</if>
update_time = now()
where
id = #{id}
</update>
<!--void updateById(ProductSku productSku);-->
<update id="updateById">
update product_sku set
<if test="skuCode != null and skuCode != ''">
sku_code = #{skuCode},
</if>
<if test="skuName != null and skuName != ''">
sku_name = #{skuName},
</if>
<if test="productId != null and productId != ''">
product_id = #{productId},
</if>
<if test="thumbImg != null and thumbImg != ''">
thumb_img = #{thumbImg},
</if>
<if test="salePrice != null and salePrice != ''">
sale_price = #{salePrice},
</if>
<if test="marketPrice != null and marketPrice != ''">
market_price = #{marketPrice},
</if>
<if test="costPrice != null and costPrice != ''">
cost_price = #{costPrice},
</if>
<if test="stockNum != null and stockNum != ''">
stock_num = #{stockNum},
</if>
<if test="skuSpec != null and skuSpec != ''">
sku_spec = #{skuSpec},
</if>
<if test="weight != null and weight != ''">
weight = #{weight},
</if>
<if test="volume != null and volume != ''">
volume = #{volume},
</if>
<if test="status != null and status != ''">
status = #{status},
</if>
update_time = now()
where
id = #{id}
</update>
<!-- void updateById(ProductDetails productDetails);-->
<update id="updateById">
update product_details set
<if test="productId != null and productId != ''">
product_id = #{productId},
</if>
<if test="imageUrls != null and imageUrls != ''">
image_urls = #{imageUrls},
</if>
update_time = now()
where
id = #{id}
</update>
五、删除商品
需求说明:
当点击删除按钮的时候此时需要弹出一个提示框,询问是否需要删除数据?如果用户点击是,那么此时向后端发送请求传递id参数,后端接收id参数进行逻辑删除。效果如下所示:
来到controller层,获取到要删除商品的id值
业务层涉及到三张表,对应着三个mapper操作语句
三个SQL语句编写如下:
@Update("update product set update_time = now() , is_deleted = 1 where id = #{id}")
void deleteById(Long id);
@Update("update product_sku set update_time = now() ,is_deleted = 1 where product_id = #{productId}")
void deleteByProductId(Long id);
@Update("update product_details set update_time = now() ,is_deleted = 1 where product_id = #{productId}")
void deleteByProductId(Long id);
六、商品审核
需求说明:
当点击审核按钮的时候此时需要弹出一个对话框,在该对话框中展示商品的详情信息,用户可以在该对话框中点击通过或者驳回按钮对商品进行审核操作。效果如下所示:
debug来到controller层,获取到要设置的商品id值、状态值
业务层的mapper接口前面已经实现过了,如果状态值为1,则表名审批通过;反之审批不通过。
七、商品上下架
商品上下架的逻辑跟商品审核类似,对比一下即可。
其中的mapper接口方法前面也已经实现过了