service数据保存_淘淘商城项目学习日记-03-商品规格参数保存相关实现

淘淘商城-商品规格参数保存说明

课程计划

内容复习:

  1. 商品添加功能
    1. 商品类目的选择。easyUI异步tree的使用
    2. 图片上传
      1. 图片服务器。http服务、ftp服务
      2. 使用kindEditor的图片上传插件实现上传,返回结果是一个json形式的字符串。
    3. 富文本编辑器的使用
      1. 引用富文本编辑器的js
      2. Jsp中添加一个textarea控件
      3. 基于textarea控件创建富文本编辑器。调用kindEditor的create方法。
      4. 表单提交前,需要把富文本编辑器的内容和textarea同步,Sync方法。

今天的内容:

  1. 商品描述的保存
  2. 商品规格的添加及使用
  3. 使用多个表实现商品规格
  4. 使用模板实现商品规格

商品描述的保存

后台要接收前台页面提交的商品信息,及商品描述。商品信息保存还要保存商品描述。

数据库中商品信息和商品描述是分开存储的。

bcba99bd84a1eeb30143985b7435392c.png

Dao层

把商品描述信息保存到tb_item_desc表中。可以使用逆向工程生成的代码

Service层

接收商品描述调用dao把商品描述插入到表中。

参数:String 商品描述

返回值:TaotaoResult

@Override
public TaotaoResult createItem(TbItem item, String desc) throws Exception {
		//item补全:生成商品ID
		Long itemId = IDUtils.genItemId();
		item.setId(itemId);
		// '商品状态,1-正常,2-下架,3-删除',
		item.setStatus((byte) 1);
		item.setCreated(new Date());
		item.setUpdated(new Date());
		//插入到数据库
		itemMapper.insert(item);
		//添加商品描述信息
		TaotaoResult result = insertItemDesc(itemId, desc);
if (result.getStatus() != 200) {
throw new Exception();
		}
return TaotaoResult.ok();
	}
	/**
	 * 添加商品描述
	 * <p>Title: insertItemDesc</p>
	 * <p>Description: </p>
	 * @param desc
	 */
private TaotaoResult insertItemDesc(Long itemId, String desc) {
		TbItemDesc itemDesc = new TbItemDesc();
		itemDesc.setItemId(itemId);
		itemDesc.setItemDesc(desc);
		itemDesc.setCreated(new Date());
		itemDesc.setUpdated(new Date());
		itemDescMapper.insert(itemDesc);
return TaotaoResult.ok();
	}

Controller

接收商品描述信息。

2eeb12291e6a11e62fea730e11340dcb.png

商品规格

什么是商品规格

92cb73a4f8e6403dd0af3ac9883e77e1.png

规格参数:

规格组

|-规格项:规格值

规律:

1、同一类商品的规格项分组相同。

2、同一类商品的规格项目是相同的。规格项目是跟商品关联。

3、不同商品规格参数的值是不同的

实现方案

方案一:使用多个表来存储

  • 每一类商品有多个分组
  • 每个分组下有多个项
  • 每个商品对应不同的规格参数

1fa68114a089e5da69f3d189fcfbdc26.png

使用二维表来维护规格数据

a43426093407191382f36d28fb7be453.png

Sql语句

SELECT
	pg.group_name,pk.param_name,pv.param_value
FROM
	tb_item_param_value pv
LEFT JOIN tb_item_param_key pk ON pv.param_id = pk.id
LEFT JOIN tb_item_param_group pg ON pk.group_id = pg.id
WHERE
	item_id = 855739

方案一存在的问题:

  • 需要创建多张表来描述规格参数之间的关系
  • 查询时需要复杂的sql语句查询
  • 规格参数数据量是商品信息的几十倍,数据量十分庞大。查询时效率很低
  • 如果要求新添加的商品规格项发生改变,之前的商品不变是不能实现的

方案二:使用模板进行管理

方案分析

可以使用模板的思路来解决此问题,每一个商品分类对一个规格参数模板。

[
    {
        "group": "主体",  //组名称
        "params": [ // 记录规格成员
            "品牌",
            "型号",
            "颜色",
            "上市年份",
            "上市月份"
        ]
},
{
        "group": "网络",  //组名称
        "params": [ // 记录规格成员
            "4G",
            "3G,
            "2G"
        ]
}
]

使用模板

每个商品对应一唯一的规格参数。在添加商品时,可以根据规格参数的模板。生成一个表单。保存规格参数时。还可以生成规格参数的json数据。保存到数据库中。

[
    {
        "group": "主体",
        "params": [
            {
                "k": "品牌",
                "v": "苹果(Apple)"
            },
            {
                "k": "型号",
                "v": "iPhone 6 A1589"
            },
{
                "k": "智能机",
                "v": "是 "
            }

        ]
}
]

实现流程

4b10fa37d6c7346e2489c7d892632fee.png

数据库存储

规格参数模板表:

c189600a53caa2d84cb7f5ed746bd6f2.png

商品的规格参数表:

1f0a442a6f6d1c9575fd79394964c2bd.png

优点:

1、不需要做多表管理。

2、如果要求新添加的商品规格项发生改变,之前的商品不变是很简单的。

缺点:

复杂的表单和json之间的转换。对js的编写要求很高。

创建规格参数模板

选择商品分类

选择商品分类后根据选择的商品分类到tb_item_param规格参数模板表中取规格模板,取到了说明此商品分类的规格模板已经添加提示不能添加,如果没有取得正常添加。

83dade7c055fe781d600ad7208ead452.png

7fca332ba039300aec7510bf8eb31bfa.png

2ff94f7403bab0c2191a3ca8671f54c1.png

3af9de65d75e31b8f251b9d261e53dbe.png

需求分析:判断模板是否存在

请求的url:

/item/param/query/itemcatid/{itemCatId}

参数:itemCatId,从url中获得

返回值:TaotaoResult

Dao层

从tb_item_param表中根据商品分类id查询内容。

单表操作,可以实现逆向工程的代码。

Service层

功能:接收商品分类id。调用mapper查询tb_item_param表,返回结果TaotaoResult。

@Service
public class ItemParamServiceImpl implements ItemParamService {
	@Autowired
	private TbItemParamMapper itemParamMapper;
	
	@Override
	public TaotaoResult getItemParamByCid(long cid) {
		TbItemParamExample example = new TbItemParamExample();
		Criteria criteria = example.createCriteria();
		criteria.andItemCatIdEqualTo(cid);
		List<TbItemParam> list = itemParamMapper.selectByExample(example);
		//判断是否查询到结果
		if (list != null && list.size() > 0) {
			return TaotaoResult.ok(list.get(0));
		}
		
		return TaotaoResult.ok();
	}

}

Controller

接收cid参数。调用Service查询规格参数模板。返回TaotaoResult。返回json数据。

@Controller
@RequestMapping("/item/param")
public class ItemParamController {
	@Autowired
	private ItemParamService itemParamService;	
	@RequestMapping("/query/itemcatid/{itemCatId}")
	@ResponseBody
	public TaotaoResult getItemParamByCid(@PathVariable Long itemCatId) {
		TaotaoResult result = itemParamService.getItemParamByCid(itemCatId);
		return result;
	}
}

Jsp

d951f2eb39ee79806ddbf5ca01998617.png

提交规格参数模板

需求分析:提交规格参数模板信息

请求的url:/item/param/save/{cid}

请求的参数:Long cid、String paramData

返回值:TaotaoResult

Dao层

向tb_item_param表中插入记录,使用逆向工程代码。

Service层

接收参数:cid、paramData两个参数,创建一个tb_item_param表对应的pojo对象。设置好对象中的属性。调用insert方法,添加一条记录。返回TaotaoResult。

@Override
	public TaotaoResult insertItemParam(Long cid, String paramData) {
		//创建一个pojo
		TbItemParam itemParam = new TbItemParam();
		itemParam.setItemCatId(cid);
		itemParam.setParamData(paramData);
		itemParam.setCreated(new Date());
		itemParam.setUpdated(new Date());
		//插入记录
		itemParamMapper.insert(itemParam);
		return TaotaoResult.ok();
	}

Controller层

接收两个参数,从url中取cid、从参数中取 paramData。调用Service插入记录,返回TaotaoResult(json),需要使用@ResourceBody

@RequestMapping("/save/{cid}")
 @ResponseBody
 public TaotaoResult insertItemParam(@PathVariable Long cid, String paramData) {
 TaotaoResult result = itemParamService.insertItemParam(cid, paramData);
 return result;
}

规格模板提交测试

参数说明

a040504b2e845e67beb4bf5a003b7071.png

提交格式

79024bb9154db1eae5a4c64753960fca.png

规格参数的编辑、删除:自主完成

规格参数模板的使用

展示规格参数模板

应该在商品添加或者商品修改时,根据商品的分类id查询此商品分类对应的规格参数模板。根据规格参数模板,生成一个表单供用户使用。

1c02c33d5509b7469934ea189b510cc0.png

当商品类目选择完成后,调用此方法:

ba492f2741596df7bc96657823d8ac7a.png

展示规格参数表单:

请求的url:/item/param/query/itemcatid/{cid}

可以和其他功能公用同一个方法。

2856dedfac14e06b11ae96732d8c4342.png

ae8039a6d67521b4f8e2b03270abd673.png

在common.js中查看相关的信息

f3ac53fa8036929c400d0befb0f620b8.png

33c323b0132f893f1af2db7751ee4fda.png

可能存在问题分析:

测试的时候发现,针对已有规格参数的商品分类,却没有显示其对应的参数模板,通过F12窗口查看相关信息,接口访问成功,但实际上接口的部分数据却没有封装到返回结果中,控制台输出查找也没有相关的数据,此处将service层查找做了如下调整,此时能够正常查找数据,原因分析:使用mybatis逆向工程生成的dao层代码,在单表查询的时候没有自信关注每个接口的实际应用,此处出了问题一步步回退查找出错点,发现是使用的接口方法并没有将大字段的paramData检索出来,从而导致数据没有封装,页面获取和显示的数据paramData为null,此处需要参考“MyBatis中selectByExample与selectByExampleWithBLOBs”代码区别

  • ResultMapWithBLOBs 定义时,继承了BaseResultMap,并且自己特殊的字段,该字段通常是longvarchar类型,本例中content就为特殊字段。
  • content字段类型为text。故如需检索的字段中包含大字段类型时,必须用selectByExampleWithBLOBs,不检索大字段时,用selectByExample就足够了。update同样如此。

2d450e33ad3d85994e19b03cb3de15be.png

c4fec8e2087740a264daf30bd116dce2.png

ResultMapWithBLOBs映射类型是在继承BaseResultMap的基础上对应配置另一个字段paramData,因此如果仅仅只是通过selectByExample查找,其返回的数据类型是BaseResultMap,不会检索大字段paramData,如此设计也是为了减轻数据访问压力!

aab52dba959524b757334b65e5f9eae4.png

测试结果:

f382039b61eedc060312156f829e3f45.png

规格参数的提交

需求分析

在商品表单提交之前,先把规格参数的信息,转换成json数据。把json提交到后台插入到表中即可。

c943da09f065f98a55544c42ca1e52ff.png

Json数据的格式:

1、生成的规格模板数据格式

[
    {
"group": "主体",  //组名称
"params": [ // 记录规格成员
"品牌",
"型号",
"颜色",
"上市年份",
"上市月份"
        ]
},
{
"group": "网络",  //组名称
"params": [ // 记录规格成员
"4G",
"3G,
"2G"
        ]
}
]

2、生成的规格数据格式

[
    {
"group": "主体",
"params": [
            {
"k": "品牌",
"v": "苹果(Apple)"
            },
            {
"k": "型号",
"v": "iPhone 6 A1589"
            },
{
"k": "智能机",
"v": "是"
            }
        ]
}
]

dac6da6d2aa4b5ecc20ba474937f1415.png

生成规格参数json字符串的处理:

6acd4d38a1aec3e5f17857eaa8b242f8.png

只需要在Controller中添加一个参数,接收商品的规格参数即可。

Service中也需要添加一个参数,增加插入规格参数表的处理。

Service

e13cab92cd7728689895cc8575212e97.png

05b11754c9f697aef3921b630c2afc23.png

Controller

添加一个接收商品规格参数的形参,完成规格参数的传入

04c8422e3ab74526fa55abe0c7a4d97c.png

展示规格参数

分析

从表中把规格参数json数据取处理,可以在java代码中解析json数据生成html展示到jsp页面。

根据商品id查询规格参数。

请求的url:/item/{itemId}

返回结果:String(逻辑视图)

Dao层

单表查询,可以使用逆向工程

Service

接收商品id,根据商品id取规格参数。可以把json转换成java对象。遍历java对象,生成html,返回。

参数:商品id

返回值:字符串(html片段)

@Override
public String getItemParamHtml(Long itemId) {
		// 根据商品id查询规格参数
		TbItemParamItemExample example = new TbItemParamItemExample();
		com.taotao.pojo.TbItemParamItemExample.Criteria criteria = example.createCriteria();
		criteria.andItemIdEqualTo(itemId);
		// 执行查询
		// List<TbItemParamItem> list = itemParamItemMapper.selectByExample(example);
		List<TbItemParamItem> list = itemParamItemMapper.selectByExampleWithBLOBs(example);
if (list == null || list.isEmpty()) {
return "";
		}
		// 取规格参数
		TbItemParamItem itemParamItem = list.get(0);
		// 获取json数据
		String paramData = itemParamItem.getParamData();
		// 将json数据转换成java对象
		List<Map> mapList = JsonUtils.jsonToList(paramData, Map.class);
		// 遍历list生成html
		StringBuffer sb = new StringBuffer();
		sb.append("<table cellpadding="0" cellspacing="1" width="100%" border="1" class="Ptable">n");
		sb.append("	<tbody>n");
for (Map map : mapList) {
			sb.append("		<tr>n");
			sb.append("			<th class="tdTitle" colspan="2">" + map.get("group") + "</th>n");
			sb.append("		</tr>n");
			// 取规格项
			List<Map> mapList2 = (List<Map>) map.get("params");
for (Map map2 : mapList2) {
				sb.append("		<tr>n");
				sb.append("			<td class="tdTitle">" + map2.get("k") + "</td>n");
				sb.append("			<td>" + map2.get("v") + "</td>n");
				sb.append("		</tr>n");
			}
		}
		sb.append("	</tbody>n");
		sb.append("</table>");
return sb.toString();
	}

模板生成说明:

在某个网站中选择模板,右键选择“检查”查看源代码,提取相关属性,封装数据

字符转义技巧:可以通过mysql中查询编辑器完成转义,选中复制的代码,在编辑器中点击右键,选择“含引号复制”-->“JAVA/C#”,完成转义

Controller层

接收商品id,调用Service查询规格参数,返回html片段。把html片段传递给jsp。

参数:

1、商品id

2、Model

@RequestMapping("/page/item/{itemId}")
	public String showItemParam(@PathVariable Long itemId, Model model) {
		String html = itemService.getItemParamHtml(itemId);
		model.addAttribute("myhtml", html);
		return"itemparam";
	}

创建jsp测试:controller层如果传入html,则可能存在于jsp内置属性冲突,导致出错,最好命名不要有冲突

8a06681a66d403bbe5e68db95ca54d4d.png

访问连接测试:

http://localhost:8080/page/item/154684383340439

294f308d398814dbe8c2994d903d605b.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值