最近有购物车逻辑,涉及到购物车列表,这里说一下自己的实现方式,大神们有更好的方式欢迎评论区留言.
1.与前端协定好的接口协议:

[
	{
	"goodsSpecInfoList":[
	{
	"goodsId":3,
	"newPrice":127.00,
	"oldPrice":129.00,
	"specContent":"",
	"specContentInfos":[
			{
			"keyName":"长度",
			"specKeyId":1,
			"specValueId":2,
			"valueName":"8mm"
			},
			{
			"keyName":"宽度",
			"specKeyId":2,
			"specValueId":4,
			"valueName":"4m"
			}
			],
	"specImg":"珊瑚/灰色图片"
	},
	{
	"goodsId":4,
	"newPrice":135.00,
	"oldPrice":139.00,
	"specContent":"",
	"specContentInfos":[
			{
			"keyName":"长度",
			"specKeyId":1,
			"specValueId":2,
			"valueName":"8mm"
			},
			{
			"keyName":"宽度",
			"specKeyId":2,
			"specValueId":4,
			"valueName":"4m"
			}
			],
	"specImg":"水蓝/灰色图片"
	}
	],
"sellerHeadPic":"3.jpg",
"sellerId":3,
"sellerNickName":"小花"
}
]

整体的结构是:
商家基本信息(昵称 头像 id)
商品列表信息(goodsSpecInfoList)
商品1基本信息
规格具体信息(specContentInfos)
商品2基本信息
规格具体信息(specContentInfos)
2.具体实现的逻辑:
根据用户名查询购物车订单中的商家信息.然后查询每一个商家信息下面关联的商品规格信息,此处使用mybatis的collection标签.由于规格表中存储的是规格id与规格项id,所以根据规格id信息去规格项与规格表中查询了对应的规格名称与规格项名称.
3.dao接口:

public interface GoodsCartMapper
{
    // 根据商品规格id查询对应的名称
    List<SpecContentInfo> findSpecContentInfo(@Param("specContentList") List specContentList);

    // 查询购物车信息
    List<GoodsCartReturnVo> findReturnGoodsCart(String login);

}
4.dao映射配置文件(头文件以及命名空间已省略):

<!--根据规格项keyId以及valueId查询对应的名称-->
    <select id="findSpecContentInfo" parameterType="java.util.List" resultType="com.it.tao.review_springboot_mybatis.domain.goodsCart.SpecContentInfo">
        SELECT goods_spec_key.id specKeyId,goods_spec_key.`key_name`,goods_spec_value.`id` specValueId,goods_spec_value.`value_name`
        FROM goods_spec_key,goods_spec_value WHERE (goods_spec_key.id,goods_spec_value.`id`) in
        <foreach collection="specContentList"  open="(" separator="," close=")" item="specContent">
            (#{specContent.specKeyId},#{specContent.specValueId})
        </foreach>
    </select>

    <resultMap id="goodsCartReturnMap" type="com.it.tao.review_springboot_mybatis.domain.goodsCart.GoodsCartReturnVo">
        <id column="id" property="sellerId"></id>
        <collection property="goodsSpecInfoList" column="id" javaType="java.util.List" ofType="com.it.tao.review_springboot_mybatis.domain.goodsCart.GoodsSpecInfo"
                    select="findSpecContentStr"></collection>
    </resultMap>
    <!--查询商品购物车新-->
    <select id="findReturnGoodsCart" parameterType="string" resultMap="goodsCartReturnMap">
 SELECT goods_seller.id,goods_seller.`nick_name` seller_nick_name,goods_seller.`head_pic` seller_head_pic,goods_cart.`id` goods_cart_id FROM goods_cart,goods_seller
 WHERE login=#{login} AND goods_cart.`saler_id`=goods_seller.`id` GROUP BY saler_id ORDER BY saler_id
    </select>
    <!--根据商家id查询规格id,然后根据规格id查询对应的规格内容-->
    <select id="findSpecContentStr" parameterType="int" resultType="com.it.tao.review_springboot_mybatis.domain.goodsCart.GoodsSpecInfo">
        SELECT goods_id,spec_content,spec_img,old_price,new_price FROM goods_spec WHERE id IN (SELECT spec_id FROM goods_cart WHERE saler_id=#{sellerId})
    </select>

5.涉及到的实体类(省略get/set)
返回页面的购物车实体类:

public class GoodsCartReturnVo {
    private int sellerId;
    private String sellerNickName;
    private String sellerHeadPic;
    // 同一商家下关联的规格商品信息
    private List<GoodsSpecInfo> goodsSpecInfoList;
    }

购物车中商品规格基本信息:

public class GoodsSpecInfo {
    private int goodsId;
    private String specImg;
    private BigDecimal oldPrice;
    private BigDecimal newPrice;
    // 对应数据库中商品规格json字符串
    private String specContent;
    // 商品规格json字符串转化成的json对象集合,带有规格id以及规格名称
    private List<SpecContentInfo> specContentInfos;
    }

规格参数实体类:

public class SpecContentInfo {
    private int specKeyId;
    private int specValueId;
    private String keyName;
    private String valueName;
    }

规格id组合实体类:

public class SpecContentVo {
    private int specKeyId;
    private int specValueId;
    }

说明:GoodsCartReturnVo中包含GoodsSpecInfo,GoodsSpecInfo中包含SpecContentInfo

6.涉及到的表(测试数据参考):
购物车表:

DROP TABLE IF EXISTS `goods_cart`;

CREATE TABLE `goods_cart` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `saler_id` INT(11) NOT NULL COMMENT '商家id',
  `spec_id` INT(11) NOT NULL COMMENT '选择商品规格id',
  `login` VARCHAR(255) NOT NULL COMMENT '用户login字段',
  `num` INT(11) DEFAULT NULL COMMENT '购买数量',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
  `update_time` DATETIME DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='商品购物车表';

/*Data for the table `goods_cart` */

INSERT  INTO `goods_cart`(`id`,`saler_id`,`spec_id`,`login`,`num`,`create_time`,`update_time`) VALUES (1,2,1,'155984905041578',8,'2020-09-10 10:58:31','2020-09-10 13:57:44'),(2,2,2,'155984905041578',1,'2020-09-10 11:18:06',NULL),(8,3,4,'155984905041578',1,'2020-09-10 15:15:31',NULL),(9,3,3,'155984905041578',2,'2020-09-10 15:15:58',NULL),(10,4,2,'1132456',1,'2020-09-10 15:21:39',NULL);

商品规格表(spec_content存储规格id与规格项组成的json格式):

DROP TABLE IF EXISTS `goods_spec`;

CREATE TABLE `goods_spec` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `goods_id` INT(11) NOT NULL COMMENT '商品id',
  `spec_content` TEXT COMMENT '规格信息',
  `spec_img` VARCHAR(500) DEFAULT NULL COMMENT '商品规格图片',
  `old_price` DECIMAL(10,2) DEFAULT NULL COMMENT '原价',
  `new_price` DECIMAL(10,2) DEFAULT NULL COMMENT '现价',
  `stock` INT(11) DEFAULT NULL COMMENT '库存',
  `sales_num` INT(11) DEFAULT '0' COMMENT '已售件数或是已兑换件数',
  `integer_count` INT(11) DEFAULT NULL COMMENT '兑换需要的积分数',
  `integer_price` DECIMAL(10,2) DEFAULT NULL COMMENT '积分商品价格',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
  `update_time` DATETIME DEFAULT NULL COMMENT '修改时间',
  `seller_id` INT(11) DEFAULT NULL COMMENT '商家id,后台商品录入时添加商家id',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;

/*Data for the table `goods_spec` */

INSERT  INTO `goods_spec`(`id`,`goods_id`,`spec_content`,`spec_img`,`old_price`,`new_price`,`stock`,`sales_num`,`integer_count`,`integer_price`,`create_time`,`update_time`,`seller_id`) VALUES (1,1,'[{\"specKeyId\":2,\"specValueId\":3},{\"specKeyId\":1,\"specValueId\":2}]','粉色图片','119.00','109.25',25,50,NULL,NULL,'2020-09-02 13:42:31',NULL,1),(2,2,'[{\"specKeyId\":2,\"specValueId\":3},{\"specKeyId\":1,\"specValueId\":1}]','灰色图片','119.00','109.00',20,5,NULL,NULL,'2020-09-02 13:42:33',NULL,1),(3,3,'[{\"specKeyId\":2,\"specValueId\":4},{\"specKeyId\":1,\"specValueId\":2}]','珊瑚/灰色图片','129.00','127.00',30,8,NULL,NULL,'2020-09-02 13:44:17',NULL,1),(4,4,'[{\"specKeyId\":2,\"specValueId\":4},{\"specKeyId\":1,\"specValueId\":2}]','水蓝/灰色图片','139.00','135.00',20,8,NULL,NULL,'2020-09-02 13:45:08',NULL,1),(5,5,'{颜色分类\":\"黑色NNN07010OS【满2件顺丰包邮】\"}','黑色图片','69.00','64.00',20,5,5000,NULL,'2020-09-02 13:46:10',NULL,1),(6,2,'{\"颜色分类\":\"蓝绿色/15kg(所有女生,买它)\"}','蓝绿图片','39.90','35.22',5,25,NULL,NULL,'2020-09-02 13:48:30',NULL,1),(7,2,'{\"颜色分类\":\"玄黑色/60kg(天阶训练)\"}','玄黑图片','59.00','58.00',25,9,NULL,NULL,'2020-09-02 13:49:42',NULL,1),(8,3,'{\"颜色分类\":\"加厚防爆-【粉色】\"}','粉色图片','93.80','90.00',30,2,NULL,NULL,'2020-09-02 14:40:19',NULL,1),(9,4,'{\"颜色分类\":\"3米加长版20磅天青蓝【推荐健身女士】\"}','青蓝图片','119.28','110.28',85,94,NULL,NULL,'2020-09-02 14:42:19',NULL,1),(10,6,'{\"颜色分类\":\"【限量抢买送固定扣】两根-长80cm【159-165cm选择】\"}','规格图片','33.50','32.59',50,8,NULL,NULL,'2020-09-02 15:10:55',NULL,1),(11,7,'{\"颜色分类\":\"独立按摩瑜伽柱(45cm)天青*赠收纳包\"}','天青图片','129.00','30.25',50,2,6000,NULL,'2020-09-02 15:13:42',NULL,1),(12,2,'测试新增规格00','规格图片','19.25','20.85',20,NULL,20,'25.98','2020-09-05 15:47:13',NULL,2),(21,14,'[{\"specKeyId\":1,\"specValueId\":21},{\"specKeyId\":10,\"specValueId\":25}]','商品图片','25.98','36.98',25,0,0,NULL,'2020-09-07 15:53:20',NULL,2),(22,14,'[{\"specKeyId\":1,\"specValueId\":22},{\"specKeyId\":10,\"specValueId\":24}]','商品图片','29.68','28.56',50,0,NULL,NULL,'2020-09-07 16:19:54',NULL,2);

规格表(其他字段已忽略):

购物车实时计算价格存redis_java


规格项表(其他字段已忽略):

购物车实时计算价格存redis_spring_02


7.逻辑层数据处理:

// 查询购物车列表
        List<GoodsCartReturnVo> goodsCartNew = goodsCartMapper.findReturnGoodsCart("155984905041578");
        System.out.println(goodsCartNew);
        for (GoodsCartReturnVo goodsCartNewVo : goodsCartNew) {
            List<GoodsSpecInfo> goodsSpecInfoList = goodsCartNewVo.getGoodsSpecInfoList();
            for (GoodsSpecInfo goodsSpecInfo : goodsSpecInfoList) {
                //ArrayList<List<SpecContentInfo>> specContentInfoArrayList = new ArrayList<>();
                String specContent = goodsSpecInfo.getSpecContent();
                // 将json字符串转化成json对象集合
                List<SpecContentVo> SpecContentVos = JSONArray.parseArray(specContent, SpecContentVo.class);
                // 根据规格id以及规格项id获取对应的名称
                List<SpecContentInfo> specContentInfo = goodsCartMapper.findSpecContentInfo(SpecContentVos);
                goodsSpecInfo.setSpecContentInfos(specContentInfo);
                // 清空json格式的规格id
                goodsSpecInfo.setSpecContent("");
            }
        }
        System.out.println(JSONObject.toJSONString(goodsCartNew));

8.说明:由于goods_spec中的spec_content中存储的是规格id与规格项id的json字符串,所以需要调用findSpecContentInfo方法将对应的名称查询出来.