Day4 商品管理

Day4 商品管理

这里会总结构建项目过程中遇到的问题,以及一些个人思考!!

学习方法:

1 github源码 + 文档 + 官网

2 内容复现 ,实际操作

项目源码同步更新到github 欢迎大家star~ 后期会更新并上传前端项目

编写品牌服务

/*** Brand service 实现common中的类** @author bootsCoder* @date created on 2024/4/15*/
@DubboService
@Transactional
public class BrandServiceImpl implements BrandService {@Autowiredprivate BrandMapper brandMapper;/*** 根据id查询品牌* @param id* @return*/@Overridepublic Brand findById(Long id) {if (id == 0){int i = 1/0; // 模拟系统异常}else if(id == -1){throw new MyException(ResultCode.PARAMETER_ERROR); // 模拟业务异常}return brandMapper.selectById(id);}@Overridepublic List<Brand> findAll() {return brandMapper.selectList(null);}@Overridepublic void add(Brand brand) {brandMapper.insert(brand);}@Overridepublic void update(Brand brand) {brandMapper.updateById(brand);}@Overridepublic void delete(Long id) {brandMapper.deleteById(id);}@Overridepublic Page<Brand> search(Brand brand, int page, int size) {QueryWrapper<Brand> queryWrapper = new QueryWrapper();// 判断品牌名是否为空if (brand != null && StringUtils.hasText(brand.getName())){queryWrapper.like("name",brand.getName());}Page page1 = brandMapper.selectPage(new Page(page, size), queryWrapper);return page1;}
}

Brand 完成

商品类型


@DubboService
@Transactional
public class ProductTypeServiceImpl implements ProductTypeService {@Autowiredprivate ProductTypeMapper productTypeMapper;@Overridepublic void add(ProductType productType) {// 根据父类型id查询父类型ProductType productTypeParent = productTypeMapper.selectById(productType.getParentId());// 根据父类型的级别,来设置当前类型的级别if (productTypeParent == null){ // 如果没有父类型,则为1级类型productType.setLevel(1);} else if (productTypeParent.getLevel() < 3) { // 如果父类型级<3 则级别为父级别+1productType.setLevel(productTypeParent.getLevel() + 1);} else if (productTypeParent.getLevel() == 3){ // 如果父类型级=3 则不能添加子级别throw new MyException(ResultCode.INSERT_PRODUCT_TYPE_ERROR);}productTypeMapper.insert(productType);}
}
image-20240418202927525

image-20240418203000901

商品规格项

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bootscoder.shopping_goods_service.mapper.SpecificationMapper"><resultMap id="specificationMapper" type="com.bootscoder.shopping_common.pojo.Specification"><id property="id" column="bid"></id><result property="specName" column="specName"></result><result property="productTypeId" column="productTypeId"></result><collection property="specificationOptions" column="specId" ofType="com.bootscoder.shopping_common.pojo.SpecificationOption"><id property="id" column="oid"></id><result property="optionName" column="optionName"></result><result property="specId" column="specId"></result></collection></resultMap><select id="findById" parameterType="long" resultMap="specificationMapper">SELECTboots_specification.id AS bid,boots_specification.specName,boots_specification.productTypeId,boots_specification_option.id AS oid,boots_specification_option.optionName,boots_specification_option.specIdFROMboots_specificationLEFT JOIN boots_specification_optionON boots_specification.id = boots_specification_option.specIdWHEREboots_specification.id = #{id}</select><select id="findByProductTypeId" parameterType="long" resultMap="specificationMapper">SELECTboots_specification.id AS bid,boots_specification.specName,boots_specification.productTypeId,boots_specification_option.id AS oid,boots_specification_option.optionName,boots_specification_option.specIdFROMboots_specificationLEFT JOIN boots_specification_optionON boots_specification.id = boots_specification_option.specIdWHEREboots_specification.productTypeId = #{productTypeId}</select>
</mapper>

image-20240418203835521

文件服务模块

搜索成功

分页查询成功

# 端口号
server:port: 9003# 日志格式
logging:pattern:console: '%d{HH:mm:ss.SSS} %clr(%-5level) ---  [%-15thread] %cyan(%-50logger{50}):%msg%n'spring:application:name: shopping_file_service #服务名cloud:nacos:discovery:server-addr: 192.168.66.100:8848 # 注册中心地址dubbo:application:name: shopping_file_service #服务名serialize-check-status: DISABLEcheck-serializable: falseprotocol:name: dubbo # 通讯协议port: -1 # 端口号,-1表示自动扫描可用端口。registry:address: nacos://192.168.66.100:8848 # 注册中心fdfs:so-timeout: 3000connect-timeout: 6000tracker-list: # TrackerList路径- 192.168.66.100:22122fileUrl: http://192.168.66.100:81 # 自定义配置,文件访问路径

文件服务实现

安装+配置+启动 fastdfs 和nginx

@DubboService
public class FileServiceImpl implements FileService {@Autowiredprivate FastFileStorageClient fastFileStorageClient;@Value("${fdfs.fileUrl}")private String fileUrl; // Nginx访问FastDFS中文件的路径@Overridepublic String uploadImage(byte[] fileBytes, String fileName) {if (fileBytes.length != 0) {try {// 1.将文件的字节数组转为输入流ByteArrayInputStream inputStream = new ByteArrayInputStream(fileBytes);// 2.获取文件的后缀名String fileSuffix = fileName.substring(fileName.lastIndexOf(".") + 1);// 3.上传文件StorePath storePath = fastFileStorageClient.uploadFile(inputStream, inputStream.available(), fileSuffix, null);// 4.返回图片路径String imageUrl = fileUrl + "/"+storePath.getFullPath();return imageUrl;}catch (Exception e){throw new BusException(CodeEnum.UPLOAD_FILE_ERROR);}} else {throw new BusException(CodeEnum.UPLOAD_FILE_ERROR);}}@Overridepublic void delete(String filePath) {fastFileStorageClient.deleteFile(filePath);}
}

上传文件时使用springMVC 将文件转换为multipartFile

—>对象没有进行序列化

消费者和生产者使用dubbo进行服务调用;数据需要实现接口序列化

–> 需要进行byte数组转换

删除的时候直接根据文件路径进行删除

上传的图片存到了服务器中
image-20240418210759579

image-20240418210824087

image-20240418211544802

在考虑后期是不是可以把这个图床配置一下改到我的oss 阿里云的图床上面;或者把服务器的配置改到其他的服务器上面是不是也可行(如果没有端口限制就好了)

测试商品增删查改功能

 @Overridepublic void add(Goods goods) {// 插入商品数据goodsMapper.insert(goods);// 插入图片数据Long goodsId = goods.getId(); // 获取商品主键List<GoodsImage> images = goods.getImages(); // 商品图片集合for (GoodsImage image : images) {image.setGoodsId(goodsId); // 给图片设置商品idgoodsImageMapper.insert(image); // 插入图片}// 插入商品_规格项数据// 1.获取规格List<Specification> specifications = goods.getSpecifications();// 2.获取规格项List<SpecificationOption> options = new ArrayList();// 3.1 遍历规格,获取规格中的所有规格项for (Specification specification : specifications) {options.addAll(specification.getSpecificationOptions());}// 3.2 遍历规格项,插入商品_规格项数据for (SpecificationOption option : options) {goodsMapper.addGoodsSpecificationOption(goodsId,option.getId());}}

关于逻辑:

这里注意一下商品的信息一般不能删除,涉及到用户的订单,将无法查找到对应的商品信息;

添加一个逻辑删除的功能即可

image-20240418212634076

存在的bug:

  1. 无法查看商品
  2. 无法在商品介绍中添加图片
  3. 注释ES后无法查看商品最后一张商品的信息;但是可以查看第一张图片的商品信息;删除本地记录后 等待30s 第一张图片也无法访问; 刷新后又可以进行访问

猜测:

因为新插入的图片没来得及和中间表关联

image-20240418214430886

image-20240418214519089

image-20240418214642662

观察后发现后端数据库中出现了奇怪的拼接

image-20240418235054619image-20240419020718124

检测到问题;代码中的联表方法必须有规格才能查看

<select id="findById" parameterType="long" resultMap="goodsMapper">SELECTboots_goods.id AS bid,boots_goods.goodsName AS goodsName,boots_goods.caption AS caption,boots_goods.price AS price,boots_goods.headerPic AS headerPic,boots_goods.introduction AS introduction,boots_goods.isMarketable AS isMarketable,boots_goods.brandId AS brandId,boots_goods.productType1Id AS productType1Id,boots_goods.productType2Id AS productType2Id,boots_goods.productType3Id AS productType3Id,boots_goods_image.id AS imageId,boots_goods_image.imageTitle AS imageTitle,boots_goods_image.imageUrl AS imageUrl,boots_specification.id AS specificationId,boots_specification.specName AS specName,boots_specification.productTypeId AS productTypeId,boots_specification_option.id AS optionId,boots_specification_option.optionName AS optionNameFROMboots_goodsLEFT JOIN boots_goods_image ON boots_goods.id = boots_goods_image.goodsIdLEFT JOIN boots_goods_specification_option ON boots_goods.id = boots_goods_specification_option.gidLEFT JOIN boots_specification_option ON boots_goods_specification_option.optionId = boots_specification_option.idLEFT JOIN boots_specification ON boots_specification_option.specId = boots_specification.idWHEREboots_goods.id = #{gid}
</select>

image-20240419022649213

从inner修改到left后发现,可以正常查询

慢sql 多表联查问题(乌龙)

出现的新问题,出现了慢sql语句; --> 点击一次查看后很难快速点击下一次查看

Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665]
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665]
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]

这些日志信息来自使用 MyBatis 框架的 Java 应用程序,在事务处理过程中记录了各个步骤。下面是每条日志的详细解释:

  1. Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665][org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]: 这表示两个不同的 SqlSession 实例正在从事务管理中释放。这通常发生在事务即将完成时,MyBatis 准备将这些会话返回到会话池中。
  2. Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665][org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]: 这表示两个 SqlSession 实例正在提交它们的事务。在这一步,所有的更改(如果有的话)被保存到数据库中。
  3. Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665][org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]: 这说明这两个 SqlSession 实例正在从事务同步管理中注销。这通常发生在事务提交或回滚之后。
  4. Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12e56665][org.apache.ibatis.session.defaults.DefaultSqlSession@2bef026]: 这表示这两个 SqlSession 实例正在关闭。关闭操作确保所有的资源都被适当释放,连接被归还到数据库连接池。

提问:如果只是简单的慢sql的话,那么为什么长时间没有反应呢?image-20240419023337509

经过postman和浏览器访问后,重复点击多次仍然有响应,考虑是前端的问题

  1. 缓存问题:可能浏览器或前端应用缓存了第一次请求的结果。您可以尝试禁用缓存或在请求时添加时间戳来确保每次请求都是唯一的。
  2. 后端接口状态问题:如果后端接口在处理完第一次请求后有状态变化或未正确关闭资源(例如数据库连接),可能导致后续请求无法处理。
  • Phantom Reads:虽然REPEATABLE-READ保证了不会出现不一致的重复读,但它不能完全防止幻读。幻读是指在一个事务内读取某范围的记录时,另一个事务插入了新记录,再次查询时看到了新的、之前不存在的记录。在REPEATABLE-READ下,通过间隙锁可以部分避免幻读,但在某些情况下仍然可能发生。

md 我真出现了 之前的图片出现在不同的mysql 的不同的数据中image-20240419032418665

目前暂时未检查出mysql数据库的死锁

邪门了 就只有这一个玩意不能多次查看, 而且是一点完别的本来嫩点的也不能点了

image-20240419031705750

image-20240419032127549

卧槽找到了 isMarkatebal 改变;上下架不改变其值;无效;;;还是不行

修复了!卧槽 因为之前的规格里面没选机身内存image-20240419034353337

image-20240419035010725

image-20240419035105025

image-20240419035135926

image-20240419035223273

前端的查询逻辑可能有点问题;

image-20240419040320145

我还是觉得很神奇; 难道是点击事件认为这件事还没有做完 所以没有cancel?

秒杀商品成功

这里多bb一嘴哈, 因为昨天晚上电脑开虚拟机卡爆了,强制重启,导致文件有损坏;没想到typora 给我留了一个文件夹进行历史恢复,真的cool;详情见偏好设置,未保存文档;(好像还有一个是历史文档的东东, 之前那个旧版本没有, 直接找楠妮儿 要到了她的正版序列号,nice!然后重新配置了一下图床)

image-20240422133235253

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/314333.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java集合相关的List、Set、Map基础知识

目录 一、集合介绍 二、List 三、Map HashMap的数据结构 如何理解红黑树 四、set 一、集合介绍 在Java中&#xff0c;集合是一种用于存储对象的数据结构&#xff0c;它提供了一种更加灵活和强大的方式来处理和操作数据。Java集合框架提供了一系列接口和类&#xff0c;用…

表格的单元格合并和表头的合并——vxe-table

vxe-table的官网&#xff1a;https://vxetable.cn/#/table/advanced/mergeCell在你的项目中下载安装完成后&#xff0c;先在main.js文件中引入&#xff1a; import VXETable from vxe-table import vxe-table/lib/style.css Vue.use(VXETable)一、单元格合并 效果图&#xff…

Linux驱动开发——(七)Linux阻塞和非阻塞IO

目录 一、阻塞和非阻塞IO简介 二、等待队列 2.1 等待队列头 2.2 等待队列项 2.3 将队列项添加/移除等待队列头 2.4 等待唤醒 2.5 等待事件 三、轮询 四、驱动代码 4.1 阻塞IO 4.2 非阻塞IO 一、阻塞和非阻塞IO简介 IO指的是Input/Output&#xff0c;也就是输入/输…

JavaWeb--06Vue组件库Element

Element 1 Element组件的快速入门1.1 Table表格 1 Element组件的快速入门 https://element.eleme.cn/#/zh-CN Element是饿了么团队开发的 接下来我们来学习一下ElementUI的常用组件&#xff0c;对于组件的学习比较简单&#xff0c;我们只需要参考官方提供的代码&#xff0c;然…

SSH新功能揭秘:远程工作提升指南【AI写作】

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

同态加密原理解析

目录 1.数学介绍2.使用多项式环进行加密2.1 私钥和公钥的产生2.2 加密2.3 解密 3.同态计算3.1 同态加法3.2 同态乘法 1.数学介绍 同态加密方案基于一个难以计算的问题Ring Learning with Errorsred。这些方案中的数据在加密和未加密时都用多项式表示。 这里举一个简单的多项式…

什么是IIoT?

什么是IIoT? IIoT&#xff0c;即工业物联网&#xff08;Industrial Internet of Things&#xff09;&#xff0c;是指将物联网技术应用到工业领域&#xff0c;通过微型低成本传感器、高带宽无线网络等技术手段&#xff0c;实现工业设备、系统和服务的互联互通&#xff0c;从而…

ChatGPT/GLM API使用

模型幻觉问题 在自然语言处理领域&#xff0c;幻觉&#xff08;Hallucination&#xff09;被定义为生成的内容与提供的源内容无关或不忠实&#xff0c;具体而言&#xff0c;是一种虚假的感知&#xff0c;但在表面上却似乎是真实的。产生背景 检索增强生成&#xff08;RAG&…

基于MLP算法实现交通流量预测(Pytorch版)

在海量的城市数据中&#xff0c;交通流量数据无疑是揭示城市运行脉络、洞察出行规律的关键要素之一。实时且精准的交通流量预测不仅能为交通规划者提供科学决策依据&#xff0c;助力提升道路使用效率、缓解交通拥堵&#xff0c;还能为公众出行提供参考&#xff0c;实现个性化导…

算法 || 二分查找

目录 二分查找 在排序数组中查找元素的第一个和最后一个位置 搜索插入位置 一个数组经过划分后具有二段性的都可以用二分查找 二分查找 704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; ​ 暴力解法&#xff1a;直接遍历数组&#xff0c;找到 target 便返回下标&am…

原型链prototype、__proto、constructor的那些问题整理

再了解原型链之前,我们先来看看构造函数和实例对象的打印结构 - 函数 这里我们定义一个构造函数Fn,然后打印它的结构吧 function Fn(){} console.dir(Fn)控制台得到结构 从上面结构我们能看的出来,函数有两种原型,一种是作为函数特有的原型:prototype,另一种是作为对象的__…

低代码技术的全面应用:加速创新、降低成本

引言 在当今数字化转型的时代&#xff0c;企业和组织面临着不断增长的应用程序需求&#xff0c;以支持其业务运营和创新。然而&#xff0c;传统的软件开发方法通常需要大量的时间、资源和专业技能&#xff0c;限制了企业快速响应市场变化和业务需求的能力。在这样的背景下&…

chrome浏览器安装elasticsearch的head可视化插件

head插件简介 elasticsearch-head被称为是弹性搜索集群的web前端&#xff0c;head插件主要是用来和elastic Cluster交互的Web前端 head插件历史 elasticsearch-head插件在0.x-2.x版本的时候是集成在elasticsearch内的&#xff0c;由elasticsearch的bin/elasticsearch-plugin…

区块链 | OpenSea 相关论文:Toward Achieving Anonymous NFT Trading(一)

​ &#x1f951;原文&#xff1a; Toward Achieving Anonymous NFT Trading &#x1f951;写在前面&#xff1a; 本文对实体的介绍基于论文提出的方案&#xff0c;而非基于 OpenSea 实际采用的方案。 其实右图中的 Alice 也是用了代理的&#xff0c;不过作者没有画出来。 正文…

基于SpringBoot + Vue实现的校园(通知、投票)管理系统设计与实现+毕业论文(12000字)+答辩PPT+指导搭建视频

目录 项目介绍 运行环境 技术栈 效果展示 论文展示 总结 项目介绍 本系统包含管理员、用户、院校管理员三个角色。 管理员角色&#xff1a;用户管理、院校管理、单位类别管理、院校管理员管理、单位管理、通知推送管理、投票信息管理、通知回复管理等。 用户角色&#…

sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

数据结构—单链表

含义 1.顺序表的回顾 之前的文章已经谈到了顺序表&#xff0c;关于顺序表&#xff0c;有一下的几种特点 1.中间&#xff0c;头部的删除&#xff0c;复杂度为O(N); 2.增容会有申请新的空间&#xff0c;拷贝数据&#xff0c;释放旧的空间&#xff0c;会有不小的消耗&#xff…

数据结构:最小生成树(Prim算法和Kruskal算法)、图的最短路径(Dijkstra算法和Bellman-Ford算法)

什么是最小生成树&#xff1f;Prim算法和Kruskal算法是如何找到最小生成树的&#xff1f; 最小生成树是指在一个连通图中&#xff0c;通过连接所有节点并使得总权重最小的子图。 Prim算法和Kruskal算法是两种常用的算法&#xff0c;用于寻找最小生成树。 Prim算法的步骤如下&…

mysql的多表查询和子查询

多表查询&#xff1a;查询数据时&#xff0c;需要使用多张表来查询 多表查询分类&#xff1a; 1.内连接查询 2.外连接查询 3.子查询 笛卡尔积&#xff1a; create table class (id int primary key auto_increment,name varchar(10) ); create table student (id int primar…

学习STM32第十六天

RTC实时时钟 一、简介 RTC是一个独立的BCD格式定时器&#xff0c;提供一个时钟日历&#xff0c;两个可编程报警中断&#xff0c;一个具有中断功能周期性可编程唤醒标志&#xff0c;RTC和时钟配置系统处于后备区域。 通过两个32位寄存器以BCD格式实现秒、分钟、小时&#xff08…