谷粒商城实战笔记-77-商品服务-API-平台属性-规格参数列表

news2024/9/9 1:40:57

文章目录

  • 一,新增product/attr/base/list接口
  • 二,踩坑记录
    • 1. 使用 `@Lazy` 注解
    • 2. 使用 `@PostConstruct` 注解
      • 代码分析
      • 解决方案分析

这一节的主要内容是完成规格参数的列表查询功能。

在这里插入图片描述

一,新增product/attr/base/list接口

这个接口用来查询规格参数列表。

	@RequestMapping("/base/list/{catelogId}")
    public R list(@RequestParam Map<String, Object> params,@PathVariable Long catelogId){
        PageUtils page = attrService.queryBaseAttrPage(params, catelogId);

        return R.ok().put("page", page);
    }

在这里插入图片描述

考虑到前端展示属性信息包含其所属分类和分组信息,我们用一个VO来封装响应数据。

在这里插入图片描述

后端实现如下。

public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();

        if(catelogId != 0){
            queryWrapper.eq("catelog_id",catelogId);
        }

        String key = (String) params.get("key");
        if(StrUtil.isNotEmpty(key)){
            //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();
        List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {
            AttrRespVo attrRespVo = new AttrRespVo();
            BeanUtils.copyProperties(attrEntity, attrRespVo);

            //1、设置分类和分组的名字
            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());
            }

            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                attrRespVo.setCatelogName(categoryEntity.getName());
            }
            return attrRespVo;
        }).collect(Collectors.toList());

        pageUtils.setList(respVos);
        return pageUtils;

在这段代码中,有一个开发中需要遵循的原则:避免使用JOIN查询以提高性能

在数据库查询中,JOIN操作可能导致性能问题,尤其是涉及多表关联时。JOIN操作会增加查询复杂度,可能导致大量的磁盘I/O操作和CPU计算开销,尤其是在处理大数据量时。此外,JOIN查询还可能因索引失效而进一步降低查询效率,尤其是在没有适当索引支持的情况下。因此,减少JOIN操作是提高查询性能的有效手段之一。

具体来说,代码通过在关联表中冗余存储分类名称和分组名称,从而避免了在查询时进行表的JOIN操作。

代码首先通过QueryWrapper构建查询条件,并执行分页查询获取AttrEntity对象列表。随后,遍历这些对象,通过额外的查询操作来获取分类名称和分组名称,而不是直接通过JOIN操作获取这些信息。

这种做法的必要性在于,JOIN操作可能会导致性能瓶颈,尤其是在涉及多表关联查询的情况下。

二,踩坑记录

启动项目失败,原因是出现了循环依赖。

在这里插入图片描述

The dependencies of some of the beans in the application context form a cycle:

   attrController (field private com.atguigu.gulimall.product.service.AttrService com.atguigu.gulimall.product.controller.AttrController.attrService)
      ↓
   attrService (field com.atguigu.gulimall.product.service.CategoryService com.atguigu.gulimall.product.service.impl.AttrServiceImpl.categoryService)
      ↓
   categoryService (field com.atguigu.gulimall.product.service.CategoryBrandRelationService com.atguigu.gulimall.product.service.impl.CategoryServiceImpl.categoryBrandRelationService)
┌─────┐
|  categoryBrandRelationService (field com.atguigu.gulimall.product.service.BrandService com.atguigu.gulimall.product.service.impl.CategoryBrandRelationServiceImpl.brandService)
↑     ↓
|  brandService (field com.atguigu.gulimall.product.service.CategoryBrandRelationService com.atguigu.gulimall.product.service.impl.BrandServiceImpl.categoryBrandRelationService)
└─────┘

当然可以。下面是针对每一种解决Spring循环依赖方法的代码示例。

1. 使用 @Lazy 注解

解决思路:通过使用 @Lazy 注解,可以让Spring容器延迟初始化bean,直到真正使用时才创建实例。

在这里插入图片描述

示例代码:

public class BrandServiceImpl extends ServiceImpl<BrandDao, BrandEntity> implements BrandService {
    @Autowired
    @Lazy
    private CategoryBrandRelationService categoryBrandRelationService;
    
    // ....
}

2. 使用 @PostConstruct 注解

解决思路

  • 这种方式不是@Lazy简单。
  • ServiceA不要自动注入ServiceB,而是提供一个public的setServiceB方法。
  • ServiceB自动注入ServiceA,且提供一个PostConstruct方法,在方法中调用ServiceA的set方法,把自身对象传递给ServiceB

示例代码:

@Service
public class ServiceA {
    private ServiceB serviceB;
    
    public void setServiceB(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
}


@Service
public class ServiceB {
	@Autowired
    private ServiceA serviceA;

    @PostConstruct
    public void setServiceB() {
        this.serviceA.setServiceB(this);
    }
}


这段代码展示了如何通过使用setter注入和@PostConstruct注解来解决循环依赖的问题。下面是对这个方案的解释:

代码分析

  1. ServiceA 类:

    @Service
    public class ServiceA {
        private ServiceB serviceB;
        
        public void setServiceB(ServiceB serviceB) {
            this.serviceB = serviceB;
        }
    }
    
    • ServiceA 类包含一个 ServiceB 类型的私有成员变量 serviceB
    • 提供了一个 setServiceB 方法来注入 ServiceB 的实例。
  2. ServiceB 类:

    @Service
    public class ServiceB {
        @Autowired
        private ServiceA serviceA;
        
        @PostConstruct
        public void setServiceB() {
            this.serviceA.setServiceB(this);
        }
    }
    
    • ServiceB 类包含一个 ServiceA 类型的私有成员变量 serviceA,并通过 @Autowired 注解自动注入。
    • 定义了一个带有 @PostConstruct 注解的方法 setServiceB,该方法在bean初始化完成后执行。
    • setServiceB 方法中,通过调用 serviceAsetServiceB 方法来设置 ServiceB 的实例。

解决方案分析

  1. setter注入:

    • ServiceAserviceB 成员变量通过setter方法注入。
    • ServiceBserviceA 成员变量通过Spring自动注入。
  2. @PostConstruct 注解:

    • ServiceB 类中的 setServiceB 方法使用了 @PostConstruct 注解,这意味着该方法将在bean初始化完成之后调用。
    • setServiceB 方法中,通过调用 serviceAsetServiceB 方法来设置 ServiceB 的实例。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电力巡检红外热成像夜视手持终端有多强?

电力巡检红外热成像夜视手持终端在电力巡检中展现出强大的功能和应用价值。这些手持终端结合了红外热成像技术和夜视功能&#xff0c;能够在夜间或光线不足的环境下对电力设备进行精确的温度测量和状态监测。以下是对其强大之处的详细分析&#xff1a; 1. 精准的红外热成像能力…

【机器学习】正规方程的简单介绍以及如何使用Scikit-Learn实现基于正规方程的闭式解线性回归

引言 Scikit-learn 是一个开源的机器学习库&#xff0c;它支持 Python 编程语言。它提供了多种机器学习算法的实现&#xff0c;并用于数据挖掘和数据分析 文章目录 引言一、正规方程的定义二、正规方程的原理三、使用 Scikit-Learn 实现基于正规方程的闭式解线性回归3.1 工具3.…

爬虫“拥抱大模型”,有没有搞头?

验证码坐标识别 数据采集过程中&#xff0c;可能会碰到各种风控策略。其中&#xff0c;验证码人机验证是较为常见的&#xff0c;点选类验证码需要识别出相应的坐标&#xff0c;碰到这种情况&#xff0c;一般要么自己训练模型&#xff0c;要么对接打码平台。现在也可以将识别工…

RocketMQ事务消息机制原理

RocketMQ工作流程 在RocketMQ当中&#xff0c;当消息的生产者将消息生产完成之后&#xff0c;并不会直接将生产好的消息直接投递给消费者&#xff0c;而是先将消息投递个中间的服务&#xff0c;通过这个服务来协调RocketMQ中生产者与消费者之间的消费速度。 那么生产者是如何…

领夹麦哪个牌子音质好?直播采访十大公认音质好的麦克风!

在追求内容品质的今天&#xff0c;音频质量成为了衡量作品成功与否的关键指标之一。对于频繁出镜的互联网从业者、短视频创作者及直播达人而言&#xff0c;一款性能卓越的无线领夹麦克风无疑是提升专业形象的得力助手。它不仅轻便易携&#xff0c;更能在复杂环境中捕捉纯净、清…

[QT开发_音乐播放器项目笔记01]

目录 一&#xff1a;常用类 26 QByteArray 是 Qt 框架中的一个类&#xff0c;用于处理字节数组。它提供了动态大小的字节数组&#xff0c;可以用于存储和操作二进制数据&#xff0c;比如文件内容、网络数据等。 QT项目记录&#xff1a; 一&#xff1a;常用类 26 QByteArray…

capl代码写法

CAPL是一种专门用于构建通信系统测试脚本的编程语言&#xff0c;全称为"Communication Access Programming.Language"。 CAPL是一种类C语言的解释性脚本语言&#xff0c;常用于CAN和LIN总线等通信系统的开发和测试中。 CAPL提供了丰富的库函数和API&#xff0c;可以用…

【Spring Cloud】Sleuth +Zinkin 实现链路追踪并持久化的解决方案

文章目录 前言链路追踪介绍Sleuth入门Sleuth介绍TraceSpanAnnotation Sleuth入门1、引入依赖2、修改配置文件3、网关路由配置4、演示 Zipkin的集成ZipKin介绍ZipKin服务端安装Zipkin客户端集成1、添加依赖2、添加配置3、访问微服务4、演示 Zipkin数据持久化使用mysql实现数据持…

vue3.0学习--创建项目,基于vite创建

vite 官网地址&#xff1a;https://cn.vitejs.dev/guide/ 1&#xff0c;执行创建命令 npm create vitelatest 2, cd my3d ---- my3d 是创建的项目名字 3&#xff0c;npm install ---- 安装需要的插件包 4&#xff0c;npm run format ---- 通常用于代码格式化 5, npm…

【Docker】Docker 的背景

一、容器技术发展史 1、Jail 时代 容器不是一个新概念或者新技术&#xff0c;很早就有了&#xff0c;只是近几年遇到了云计算&#xff0c;整个技术被彻底引爆了。 &#xff08;1&#xff09;1979 年贝尔实验室发明 chroot chroot 系统调用是在 1979 年开发第 7 版 Unix 期间…

Java多重循环控制,break,continue,return

目录 1.多重循环控制 执行步骤分析 案例演示 2.跳转控制语句-break 基本介绍 基本语法 示意图 注意事项和细节说明 练习题 3.跳转控制语句-continue 基本介绍 基本语法 示意图 细节案例分析和说明 4.跳转控制语句-return 介绍 1.多重循环控制 执行步骤分析…

django基于大数据的电影推荐系统-计算机毕业设计源码71246

目 录 摘 要 1 绪论 1.1 选题背景与意义 1.2研究现状 1.3研究内容 1.4 开发环境 1.5论文结构与章节安排 2 相关理论和技术 2.1 协同过滤算法 2.2 B/S体系结构介绍 2.3 Python爬虫技术 2.4 Django框架介绍 2.5 MySQL数据库 3 电影推荐系统系统分析 3.1 可行性分析…

微信小程序审核的一些总结记录

1、文字ocr识别工具&#xff0c;识别ocr文字&#xff0c;显示出文字 这么简单的东西&#xff0c;说是“涉及提供图片/音频/制作、剪辑服务”&#xff0c;这个工具代码也就下图几行&#xff0c;这是哪门子的图片编辑&#xff0c;别管它&#xff0c;直接重新提交审核。 2、个人不…

营销人看巴黎奥运会,看到了什么?

不同的人眼中的巴黎奥运会是不一样的&#xff1a;环保人士关注奥运场馆的绿色设计&#xff0c;以及赛事期间对可再生能源的利用&#xff1b;旅游博主用镜头捕捉巴黎奥运会每一个精彩瞬间&#xff1b;社会学家在巴黎奥运会看到多元文化的交流与融合…… 那么营销人在巴黎奥运会…

基于IDEA+MySQL+Springboot开发的医药进销存系统

基于IDEAMySQLSpringboot开发的医药进销存系统 项目介绍&#x1f481;&#x1f3fb; 1.创建数据库tedu_DIEMS&#xff0c;并导入数据库文件 2.导入项目&#xff0c;import-maven 3.修改application.properties的数据库IP地址、用户名和密码&#xff0c;改为自己的信息 4.找到Di…

嵌入式学习第11天——C语言选择结构

2024年7月29日 第11天 选择&#xff08;分支&#xff09;结构 分支结构&#xff1a;又被称为选择结构 概念 选择结构&#xff1a;根据条件成立与否&#xff0c;选择相应的操作。 条件构建 关系表达式&#xff1a;含有关系运算符的表达式&#xff08;>,<,>,<,!…

Oracle大师Roger Cornejo的推荐:使用ASH诊断Oracle解析故障

这篇文章被Oracle大师Roger Cornejo在X平台上推荐&#xff08;见下图&#xff09;&#xff0c;英文原文在&#xff1a; Diagnosing Parsing Issue with ASH 解析&#xff0c;尤其是硬解析&#xff0c;是非生产性操作&#xff0c;会消耗大量系统资源&#xff0c;导致库缓存争用…

文档数据库--MongoDB

文章目录 MongoDB介绍主要用途和特点对比关系型数据库和关系型数据库最大的不同什么时候使用MongoDBMongoDB数据结构MongoDB参考资料 MongoDB部署和访问二进制安装脚本安装MongoDB后台管理shellmongodb数据库命令mongo的helpdb.mycoll.help() mongosh的helpshow dbsuse dbnamem…

JAVA里的多线程综合练习题

练习1 package lx1;/*一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒, 要求:请用多线程模拟卖票过程并打印剩余电影票的数量*/ public class MyThread extends Thread {static int ticket 1000;//多个线程对象共享同一个电影票//第一种方式实现多线程&…

生成式:PolyGen: An Autoregressive Generative Model of 3D Meshes【附件】

论文:PolyGen: An Autoregressive Generative Model of 3D Meshes OBJ坐标变换: # Transpose so that z-axis is vertical.vertices = vertices[:, [2, 0, 1]]变换前: 对应数据: