043 商品详情
文章目录
- 详情页数据
- 表结构
- vo
- SkuItemVo.java
- SkuItemSaleAttrVo.java
- AttrValueAndSkuIdVo.java
- SpuAttrGroupVo.java
- GroupAttrParamVo.java
- pom.xml
- SkuSaleAttrValueDao.xml
- SkuSaleAttrValueDao.java
- AttrGroupDao.xml
- AttrGroupServiceImpl.java
- SkuInfoServiceImpl.java
- SkuSaleAttrValueServiceImpl.java
- AttrGroupDao.java
- SkuSaleAttrValueDao.java
- SkuItemController.java
- 默认
- 点击选中
详情页数据
1.sku基本信息
2.sku图片信息(多个图片)
3.spu的销售属性
4.spu的描述信息
5.sku分组规格参数属性值
表结构
vo
SkuItemVo.java
package com.xd.cubemall.product.vo;import com.xd.cubemall.product.entity.SkuImagesEntity;
import com.xd.cubemall.product.entity.SkuInfoEntity;
import com.xd.cubemall.product.entity.SpuInfoDescEntity;
import lombok.Data;
import lombok.ToString;import java.util.List;@ToString
@Data
public class SkuItemVo {//1.sku基本信息private SkuInfoEntity info;//2.sku图片信息private List<SkuImagesEntity> images;//3.spu的销售属性组合private List<SkuItemSaleAttrVo> attrSales;//4.spu描述信息private SpuInfoDescEntity desc;//5.spu分组(主体,基本信息...)规格属性private List<SpuAttrGroupVo> attrGroups;}
SkuItemSaleAttrVo.java
package com.xd.cubemall.product.vo;import lombok.Data;
import lombok.ToString;import java.util.List;@ToString
@Data
public class SkuItemSaleAttrVo {private Long attrId;private String attrName;//属性值private List<AttrValueAndSkuIdVo> attrValues;}
AttrValueAndSkuIdVo.java
package com.xd.cubemall.product.vo;import lombok.Data;
import lombok.ToString;@ToString
@Data
public class AttrValueAndSkuIdVo {// skuids组合idprivate String skuIds;// 属性值: 白色,128Gprivate String attrValue;
}
SpuAttrGroupVo.java
package com.xd.cubemall.product.vo;import lombok.Data;
import lombok.ToString;import java.util.List;@ToString
@Data
public class SpuAttrGroupVo {private String groupName;// 属性参数private List<Attr> attrs;
}
GroupAttrParamVo.java
package com.xd.cubemall.product.vo;import lombok.Data;
import lombok.ToString;@ToString
@Data
public class GroupAttrParamVo {private Long spuId;private Long categoryId;
}
pom.xml
<!--添加模板技术渲染页面--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
在MySQL中,当启用了ONLY_FULL_GROUP_BY SQL模式时,如果一个SELECT查询包含聚合函数(如GROUP_CONCAT),那么所有非聚合的列都必须在GROUP BY子句中明确指定。这是因为ONLY_FULL_GROUP_BY模式要求所有的结果列要么是通过聚合函数处理的,要么是在GROUP BY子句中明确指定的。
从错误信息来看,查询试图在不使用GROUP BY子句的情况下选择非聚合列v.attr_id、v.attr_name和v.attr_value,同时还使用了聚合函数GROUP_CONCAT(v.sku_id)。这违反了ONLY_FULL_GROUP_BY的规则。
为了解决这个问题,需要修改查询,添加一个GROUP BY子句,包含所有非聚合的列。这样,每个组都会有唯一的attr_id、attr_name和attr_value,而GROUP_CONCAT则会将同一组内的sku_id连接起来。
SkuSaleAttrValueDao.xml
<resultMap id="spuSaleAttrMap" type="com.xd.cubemall.product.vo.SkuItemSaleAttrVo"><result property="attrId" column="attr_id"></result><result property="attrName" column="attr_name"></result><collection property="attrValues" ofType="com.xd.cubemall.product.vo.AttrValueAndSkuIdVo"><result property="skuIds" column="skuIds"></result><result property="attrValue" column="attr_value"></result></collection></resultMap><!--sql: tb_sku_info,tb_sku_sale_attr_value--><select id="getSaleAttrs" resultMap="spuSaleAttrMap" parameterType="java.lang.Long">SELECTv.attr_id,v.attr_name,v.attr_value,GROUP_CONCAT( v.sku_id ) AS skuIdsFROMtb_sku_info iLEFT JOIN tb_sku_sale_attr_value v ON i.id = v.sku_idWHEREspu_id = #{spuId}GROUP BYv.attr_id,v.attr_name,v.attr_value;</select>
SkuSaleAttrValueDao.java
package com.xd.cubemall.product.dao;import com.xd.cubemall.product.entity.SkuSaleAttrValueEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xd.cubemall.product.vo.SkuItemSaleAttrVo;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** sku销售属性值* * @author xuedong* @email email@gmail.com* @date 2024-08-13 01:36:04*/
@Mapper
public interface SkuSaleAttrValueDao extends BaseMapper<SkuSaleAttrValueEntity> {public List<SkuItemSaleAttrVo> getSaleAttrs(Long spuId);
}
AttrGroupDao.xml
<resultMap id="spuAttrGroupMap" type="com.xd.cubemall.product.vo.SpuAttrGroupVo"><result property="groupName" column="groupName"></result><collection property="attrs" ofType="com.xd.cubemall.product.vo.Attr"><result property="attrName" column="attrName"></result><result property="attrValue" column="attrValue"></result></collection></resultMap><!--SQL: 根据spuID,categoryId 查询 sku分组规格参数属性值--><select id="getGroupAttr" resultMap="spuAttrGroupMap" parameterType="com.xd.cubemall.product.vo.GroupAttrParamVo">SELECTg.NAME AS groupName,v.attr_name AS attrName,v.attr_value AS attrValueFROMtb_product_attr_value vJOIN tb_attr_attrgroup_relation r ON v.attr_id = r.attr_idJOIN tb_attr_group g ON r.attr_group_id = g.idWHEREspu_id = #{spuId}AND g.category_id = #{categoryId}</select>
AttrGroupServiceImpl.java
//根据spuID,categoryId 查询 sku分组规格参数属性值@Overridepublic List<SpuAttrGroupVo> getGroupAttr(Long spuId, Long categoryId) {GroupAttrParamVo paramVo = new GroupAttrParamVo();paramVo.setSpuId(spuId);paramVo.setCategoryId(categoryId);List<SpuAttrGroupVo> attrGroupVos = this.baseMapper.getGroupAttr(paramVo);return attrGroupVos;}
SkuInfoServiceImpl.java
@Autowiredprivate SkuImagesService skuImagesService;//注入销售属性组合服务@Autowiredprivate SkuSaleAttrValueService skuSaleAttrValueService;//注入spu描述服务@Autowiredprivate SpuInfoDescService spuInfoDescService;@Autowiredprivate AttrGroupService attrGroupService;@Overridepublic SkuItemVo skuItem(Long skuId) {// 新建一个包装类对象SkuItemVo itemVo = new SkuItemVo();/*1.sku基本信息2.sku图片信息(多个图片)3.spu的销售属性4.spu的描述信息5.sku分组规格参数属性值*/// 1.根据skuId 查询 sku基本信息SkuInfoEntity skuInfoEntity = this.getById(skuId);itemVo.setInfo(skuInfoEntity);// 获取sku与之对应的spuIdLong spuId = skuInfoEntity.getSpuId();// 获取分类idLong categoryId = skuInfoEntity.getCategoryId();// 2.根据skuId查询sku图片信息(多个图片),skuId是外键List<SkuImagesEntity> imageList = skuImagesService.list(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId));itemVo.setImages(imageList);//3.根据spuID获取spu的销售属性List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrs(spuId);itemVo.setAttrSales(saleAttrVos);//4.根据spuId查询spu的描述信息SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getOne(new QueryWrapper<SpuInfoDescEntity>().eq("spu_id",spuId));itemVo.setDesc(spuInfoDescEntity);//5.根据spuID,categoryId查询 sku分组规格参数属性值List<SpuAttrGroupVo> attrGroupVos = attrGroupService.getGroupAttr(spuId,categoryId);itemVo.setAttrGroups(attrGroupVos);return itemVo;}
SkuSaleAttrValueServiceImpl.java
/*** 根据id查询销售属性组合* @param spuId* @return*/@Overridepublic List<SkuItemSaleAttrVo> getSaleAttrs(Long spuId) {//List<SkuItemSaleAttrVo> saleAttrVos = skuSaleAttrValueService.getSaleAttrs(spuId);List<SkuItemSaleAttrVo> saleAttrVos = this.baseMapper.getSaleAttrs(spuId);return saleAttrVos;}
AttrGroupDao.java
package com.xd.cubemall.product.dao;import com.xd.cubemall.product.entity.AttrGroupEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xd.cubemall.product.vo.GroupAttrParamVo;
import com.xd.cubemall.product.vo.SpuAttrGroupVo;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** 属性分组表* * @author xuedong* @email email@gmail.com* @date 2024-08-13 01:36:04*/
@Mapper
public interface AttrGroupDao extends BaseMapper<AttrGroupEntity> {//根据spuID,categoryId 查询 sku分组规格参数属性值public List<SpuAttrGroupVo> getGroupAttr(GroupAttrParamVo paramVo);
}
SkuSaleAttrValueDao.java
package com.xd.cubemall.product.dao;import com.xd.cubemall.product.entity.SkuSaleAttrValueEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xd.cubemall.product.vo.SkuItemSaleAttrVo;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** sku销售属性值* * @author xuedong* @email email@gmail.com* @date 2024-08-13 01:36:04*/
@Mapper
public interface SkuSaleAttrValueDao extends BaseMapper<SkuSaleAttrValueEntity> {public List<SkuItemSaleAttrVo> getSaleAttrs(Long spuId);
}
SkuItemController.java
package com.xd.cubemall.product.web;import com.xd.cubemall.product.service.SkuInfoService;
import com.xd.cubemall.product.vo.SkuItemVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@Controller
public class SkuItemController {@Autowiredprivate SkuInfoService skuInfoService;/*** 根据skuId查询商品详情信息*/@GetMapping("/{skuId}.html")public String skuItem(@PathVariable Long skuId, Model model){// 调用服务层商品详情接口SkuItemVo itemVo = skuInfoService.skuItem(skuId);// 输出日志log.info("商品详情接口,查询的数据:{}",itemVo);// 把数据放入模型驱动model.addAttribute("item",itemVo);// 返回视图页面,做视图数据渲染return "item";}
}
默认
<a href="javascript:;" th:attr="class=${#lists.contains(#strings.listSplit(attrvalues.skuIds,','),item.info.id.toString())?'sku_attr_value selected':'sku_attr_value'},skus=${attrvalues.skuIds}"><!--th:v-bind:class="|{selected:sel('${spec.key}','${arrValue}')}|"-->
<!-- th:@click="|selectSpecification('${spec.key}','${arrValue}')|" >-->
<!-- <i th:text="${arrValue}"></i>-->[[${attrvalues.attrValue}]]<span title="点击取消选择"> </span></a>
点击选中
$(".sku_attr_value").click(function () {// 移除选中状态$(this).parent().parent().find(".sku_attr_value").removeClass("selected");// 给点击元素添加选中状态属性$(this).addClass("selected");let skus = new Array();//选择不同的规格属性后,根据不同的属性id重新加载相应的数据$("a[class='sku_attr_value selected']").each(function () {skus.push($(this).attr("skus").split(","));})// 获取第0个元素let sku_1 = skus[0];// 白色: skuIds = {1,3}// 128GB : skuIds = {3,9}// 白色+128GB 规则属性组合的id : 求交集 ,skuId = 3for(let i=1;i<skus.length;i++){// 遍历每一个属性的skuids,获取交集// 比如:白色: skuIds = {1,3},128GB : skuIds = {3,9} ,此时: {1,3}.filter({3,9}) = 3sku_1 = $(sku_1).filter(skus[i])[0];}// 拼接请求location.href = "http://localhost:8081/"+sku_1+".html";})
相关文章:

043 商品详情
文章目录 详情页数据表结构voSkuItemVo.javaSkuItemSaleAttrVo.javaAttrValueAndSkuIdVo.javaSpuAttrGroupVo.javaGroupAttrParamVo.java pom.xmlSkuSaleAttrValueDao.xmlSkuSaleAttrValueDao.javaAttrGroupDao.xmlAttrGroupServiceImpl.javaSkuInfoServiceImpl.javaSkuSaleAtt…...
【人工智能】Python与Scikit-learn的模型选择与调参:用GridSearchCV和RandomizedSearchCV提升模型性能
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在机器学习建模过程中,模型的表现往往取决于参数的选择与优化。Scikit-learn提供了便捷的工具GridSearchCV和RandomizedSearchCV,帮助我们在参数空间中搜索最佳组合以提升模型表现。本文将从理论和实践两个角度…...

深入探讨 Puppeteer 如何使用 X 和 Y 坐标实现鼠标移动
背景介绍 现代爬虫技术中,模拟人类行为已成为绕过反爬虫系统的关键策略之一。无论是模拟用户点击、滚动,还是鼠标的轨迹移动,都可以为爬虫脚本带来更高的“伪装性”。在众多的自动化工具中,Puppeteer作为一个无头浏览器控制库&am…...

<OS 有关> ubuntu 24 不同版本介绍 安装 Vmware tools
原因 想用 apt-get download 存到本地 / NAS上,减少网络流浪。 看到 VMware 上的确实有 ubuntu,只是版本是16。 ubuntu 版本比较:LTS vs RR LTS: Long-Term Support 长周期支持, 一般每 2 年更新,会更可靠与更稳定…...
C#调用JAVA
参考教程:使用IKVMC转换Jar为dll动态库(含idea打包jar方法)-CSDN博客 已经实践过,好使。...

JavaEE-多线程基础知识
文章目录 前言与回顾创建一个多线程线程的创建以及运行机制简述step1: 继承Thread类step2: 实现Runable接口step3: 基于step1使用匿名内部类step4: 基于step2使用匿名内部类step5: 基于step4使用lambda表达式(推荐) Thread的常见方法关于jconsole监视线程的工具构造方法解析获取…...

Pulid:pure and lightning id customization via contrastive alignment
1.introduction 基于微调的方案,对每个id进行定制需要花费数十分钟。另一项研究则放弃了对每个id进行微调,而是选择在一个庞大的肖像数据集上预训练一个id适配器。这些方法通常利用编码器例如clip来提取id特征,提取的特征随后以特定方式例如嵌入到cross attention集成到基础…...
什么是GraphQL,有什么特点
什么是GraphQL? GraphQL 是一种用于 API(应用程序编程接口)的查询语言,由 Facebook 在 2012 年开发,并于 2015 年开源。它提供了一种更高效、强大的方式来获取和操作数据,与传统的 RESTful API 相比&#…...

Java项目-基于SpringBoot+vue的租房网站设计与实现
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

【SQL Server】华中农业大学空间数据库实验报告 实验三 数据操作
1.实验目的 熟悉了解掌握SQL Server软件的基本操作与使用方法,以及通过理论课学习与实验参考书的帮助,熟练掌握使用T-SQL语句和交互式方法对数据表进行插入数据、修改数据、删除数据等等的操作;作为后续实验的基础,根据实验要求重…...

【大数据学习 | Spark】RDD的概念与Spark任务的执行流程
1. RDD的设计背景 在实际应用中,存在许多迭代式计算,这些应用场景的共同之处是,不同计算阶段之间会重用中间结果,即一个阶段的输出结果会作为下一个阶段的输入。但是,目前的MapReduce框架都是把中间结果写入到HDFS中&…...
ruoyi框架完成分库分表,按月自动建表功能
前提 这个分库分表功能,按月自动建表,做的比较久了,还没上线,是在ruoyi框架内做的,踩了不少坑,但是已经实现了,就分享一下代码吧 参考 先分享一些参考文章 【若依系列】集成ShardingSphere S…...

Antd中的布局组件
文章目录 一、Layout二、Menu三、Grid栅格 布局组件涉及项目框架的搭建,往往被忽略和低关注,毕竟不是经常用到,但是在调整项目结构的时候往往又需要重新设计布局,所以有必要提前归纳分析; 一、Layout Layout导出Sider,…...

一文详解kafka知识点
目录 1、kafka定义 2、消息队列 2.1、产品选择 2.2、应用场景 2.3、消息队列的两种模式 3、kafka架构 4、kafka生产者 4.1、kafka生产者原理 4.2、kafka生产者异步发送 4.3、同步发送 4.4、分区 4.4.1、kafka分区好处 4.4.2、分区策略 4.4.3、自定义分区 4.5、生成吞…...

C语言基础学习:抽象数据类型(ADT)
基础概念 抽象数据类型(ADT)是一种数据类型,它定义了一组数据以及可以在这组数据上执行的操作,但隐藏了数据的具体存储方式和实现细节。在C语言中,抽象数据类型(ADT)是一种非常重要的概念&…...

提升性能测试效率与准确性:深入解析JMeter中的各类定时器
在软件性能测试领域,Apache JMeter是一款广泛使用的开源工具,它允许开发者模拟大量用户对应用程序进行并发访问,从而评估系统的性能和稳定性。在进行性能测试时,合理地设置请求之间的延迟时间对于模拟真实用户行为、避免服务器过载…...
施密特正交化与单位化的情形
在考研数学的线性代数部分,施密特正交化和单位化是两种不同的处理向量的方法,它们在特定的情况下被使用。以下是详细说明: 施密特正交化的应用场景 施密特正交化(Gram-Schmidt Orthogonalization)是一种从线性无关向…...

ROS机器视觉入门:从基础到人脸识别与目标检测
前言 从本文开始,我们将开始学习ROS机器视觉处理,刚开始先学习一部分外围的知识,为后续的人脸识别、目标跟踪和YOLOV5目标检测做准备工作。我采用的笔记本是联想拯救者游戏本,系统采用Ubuntu20.04,ROS采用noetic。 颜…...

2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略(详细解题思路)
在当下, 日益发展的时代,宠物的数量应该均为稳步上升,在美国出现了下降的趋势, 中国 2019-2020 年也下降,这部分变化可能与疫情相关。需要对该部分进行必要的解释说明。 问题 1: 基于附件 1 中的数据及您的团队收集的…...
C#里怎么样访问文件时间
C#里怎么样访问文件时间 文件时间也是一个关键信息, 因为很多数据处理需要时间来判断数据的有效性,比如股票中的股价, 它是的权重,是随着时间递减的。 一般来说,超过5年以上的数据,都是可以删除掉了。 或者说超过三年的数据,就需要压缩保存了,这样可以省掉很多磁盘空…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...