要求:
1、商品描述的保存
2、商品规格的添加及使用
2-1、使用多个表实现商品规格
2-2、使用模板实现商品规格
一、描述的保存
商品信息和描述存在两张表里
tb_item
tb_item_desc
原因商品详情介绍,不是每一次都需要,比如列表。
/** 添加商品描述 */
private TaotaoResult addItemDesc
(Long itemId, String desc) {
TbItemDesc itemDesc = new TbItemDesc();
itemDesc.setItemId(itemId);
Date timeNow = new Date();
itemDesc.setCreated(timeNow);
itemDesc.setUpdated(timeNow);
itemDesc.setItemDesc(desc);
itemDescMapper.insert(itemDesc);
return TaotaoResult.ok();
}
添加商品
public TaotaoResult addItem(TbItem item, String desc) throws Exception {
// 补全信息
Long itemId = IDUtils.genItemId();
item.setId(itemId);
item.setCreated(new Date());
item.setUpdated(new Date());
// 商品状态,1-正常,2-下架,3-删除
item.setStatus((byte) 1);
itemMapper.insert(item);
TaotaoResult result = addItemDesc(itemId,desc);
/*
* 事务控制在service 添加商品描述和商品内容都放在同一个事务中
* 如果添加描述出现异常 也就是 result.getStatus() != 200
* 抛出异常,这样 添加商品信息和 描述都会失败,不会出现脏数据
*/
if(result.getStatus() != 200) {
throw new Exception();
}
return TaotaoResult.ok();
}
ok方法
public static TaotaoResult ok() {
return new TaotaoResult(null);
}
调用ok方法,这样就相当于初始化了 status = 200 msg = OK
public TaotaoResult(Object data) {
this.status = 200;
this.msg = "OK";
this.data = data;
}
【Controller】
@RequestMapping(value="/item/save", method=RequestMethod.POST)
@ResponseBody
public TaotaoResult saveItem
(TbItem item,String desc) throws Exception {
TaotaoResult result = itemService.addItem(item, desc);
return result;
}
<textarea name="desc"> 描述</textarea>
maven启动报错
错误: 程序包org.junit不存在
原因:Controller里导出了包
import org.junit.runner.Describable;
二、商品规格
想要实现这个模型,
方案1,数据库建表
分析:通过看图可以看出
参数分了几个组,像主体,网络等。
每个组里面又有多个参数项
同时看了多个商品我们发现,同一类商品分类情况基本一样
所以分表
商品分类表 (1 : n) 规格参数分组表 一类商品对应多个分组
规格参数分组表 (1 :n) 参数项表(参数项的名称)
参数项表 (1 :n) 规格参数值[商品 id 参数项 id 参数值value]
参数项名表 tb_item_param_key
参数项值 tb_item_param_value pv
参数分组 tb_item_param_group
sql语句
查询出 规格分组名、参数项名 和参数值
引入参数项表,参数项的主键是参数值的外键
V1 写法
v2 使用外连接, where 只做筛选的作用,
A left join B
左连接A、B表结果包括A的全部记录和符合条件的B的记录。
也就是A全部有
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
总结:这种方法存在的问题
1、需要创建多张表来描述规格参数之间的关系。
2、查询时需要复杂的sql语句查询。
3、规格参数数据量是商品信息的几十倍,数据量十分庞大。查询时效率很低。
mysql 查询全表某字段值最大的10条数据
select * from 表 order by 要最大值的字段 desc limit 0,10
方案二
3.3.1 方案分析
可以使用模板的思路来解决此问题。
1、每一个商品分类对一个规格参数模板。
[
{
“group”: “主体”, //组名称
“params”: [ // 记录规格成员
“品牌”,
“型号”,
“颜色”,
“上市年份”,
“上市月份”
]
},
{
“group”: “网络”, //组名称
“params”: [ // 记录规格成员
“4G”,
“3G,
“2G”
]
}
]
2、使用模板
每个商品对应一唯一的规格参数。在添加商品时,可以根据规格参数的模板。生成一个表单。保存规格参数时。还可以生成规格参数的json数据。保存到数据库中。
[
{
“group”: “主体”,
“params”: [
{
“k”: “品牌”,
“v”: “苹果(Apple)”
},
{
“k”: “型号”,
“v”: “iPhone 6 A1589”
},
{
“k”: “智能机”,
“v”: “是 ”
}
]
}
]
3.3.3 数据库存储
规格参数模板表
商品的规格参数表:
优点:
1、不需要做多表管理。
2、如果要求新添加的商品规格项发生改变,之前的商品不变是很简单的。
缺点:
复杂的表单和json之间的转换。对js的编写要求很高。
4 创建规格参数模板
4.1 选择商品分类
选择商品分类后根据选择的商品分类到tb_item_param规格参数模板表中取规格模板,取到了说明此商品分类的规格模板已经添加提示不能添加。
如果没有取得正常添加。
* 规格参数默认是隐藏
<tr class="hide addGroupTr">
<td>规格参数:</td>
* <li class="param">
<Input title="添加参数">
$(function(){
* 页面一加载执行这个函数,初始化类目
TAOTAO.initItemCat({
fun:function(node){
* 通过class选择器定位到规格参数 然后find 添加参数删除它 $(".addGroupTr").hide().find(".param").remove();
// 判断选择的类目是否已经添加过规格
$.getJSON("/item/param/query/itemcatid/" + node.id,function(data){
if(data.status == 200 && data.data){
$.messager.alert("提示", "该类目已经添加,请选择其他类目。", undefined, function(){
$("#itemParamAddTable .selectItemCat").click();
});
return ;
}
$(".addGroupTr").show();
});
}
});
$.getJSON("/item/param/query/itemcatid/" + node.id
根据cid去查询这个类目是否已经有了模板
if(data.status == 200 && data.data)确定回参里有status
S1 写service 确定入参(cid 也就是itemCatId)
和返回值 (taotaoResult)
public TaotaoResult getItemParamById(long itemCatId) {
TbItemParamExample example = new TbItemParamExample();
Criteria criteria = example.createCriteria();
criteria.andItemCatIdEqualTo(itemCatId);
List<TbItemParam> list = itemParamMapper.selectByExample(example);
// 根据查询的结果返回数据
if(list != null && list.size() > 0) {
return TaotaoResult.ok(list);
}
return TaotaoResult.ok();
}
S2 写controller
@RequestMapping("/item/param") -债化请求
public class ItemParamController
@RequestMapping("/query/itemcatid/{itemCatId}")
@ResponseBody
public TaotaoResult queryItemParam
(@PathVariable long itemCatId) { //从入参取值
return itemParamService.getItemParamById(itemCatId);
}
如果返回data 有数据 status == 200 会提示已存在
否则 展示输入参数
$(".addGroupTr").show();
4.2 提交规格参数模板
4.2.1 需求分析
首先把页面中所有文本框中的内容转换成json数据。把json字符串提交给后台。保存到规格参数表中。
$("#itemParamAddTable .submit").click(function(){
var params = [];
var groups = $("#itemParamAddTable [name=group]");
groups.each(function(i,e){
var p = $(e).parentsUntil("ul").parent().find("[name=param]");
var _ps = [];
p.each(function(_i,_e){
var _val = $(_e).siblings("input").val();
if($.trim(_val).length>0){
_ps.push(_val);
}
});
var _val = $(e).siblings("input").val();
if($.trim(_val).length>0 && _ps.length > 0){
params.push({
"group":_val,
"params":_ps
});
}
});
var url = "/item/param/save/"+$("#itemParamAddTable [name=cid]").val();
$.post(url,{"paramData":JSON.stringify(params)},function(data){
if(data.status == 200){
$.messager.alert('提示','新增商品规格成功!',undefined,function(){
$(".panel-tool-close").click();
$("#itemParamList").datagrid("reload");
});
}
});
});
* JSON.stringify(params) js内置方法,把json转成字符串
请求的url:
/item/param/save/{cid}
S1 service 进行业务处理
public TaotaoResult addItemParam(TbItemParam itemParam) {
// 补全pojo对象
Date dateNow = new Date();
itemParam.setCreated(dateNow);
itemParam.setUpdated(dateNow);
itemParamMapper.insert(itemParam);
return TaotaoResult.ok();
}
S2 controller 在这里只是处理页面接收的参数
@RequestMapping("/save/{cid}")
@ResponseBody
public TaotaoResult addItemParam(@PathVariable long cid,String paramData) {
TbItemParam itemParam = new TbItemParam();
itemParam.setItemCatId(cid);
itemParam.setParamData(paramData);
return itemParamService.addItemParam(itemParam);
}
7 展示规格参数
当现实商品详情页面时,需要把商品的规格参数根据商品id取出来,生成html展示到页面。
7.1 Dao层
根据商品id查询规格参数,单表查询。
[
{
“group”: “主体”,
“params”: [
{
“k”: “品牌”,
“v”: “苹果(Apple)”
},
service
@Override
public String getItemParamByItemId(long itemId) {
TbItemParamItemExample example = new TbItemParamItemExample();
com.taotao.pojo.TbItemParamItemExample.Criteria criteria = example.createCriteria();
criteria.andItemIdEqualTo(itemId);
List<TbItemParamItem> list = itemParamItemMapper.selectByExampleWithBLOBs(example);
if(list == null || list.size() == 0) {
return "";
}
TbItemParamItem itemParamItem = list.get(0);
String paramData = itemParamItem.getParamData();
// 把规格参数json数据转换成java对象
List<Map> jsonList = JsonUtils.jsonToList(paramData, Map.class);
StringBuffer sb = new StringBuffer();
// 从网页上拔table 接着使用navicat 查询编辑器含引号复制
sb.append("<table cellpadding=\"0\" cellspacing=\"1\" width=\"100%\" border=\"1\" class=\"Ptable\">\n");
sb.append(" <tbody>\n");
// 取出所有分组group
for(Map m1:jsonList) {
sb.append(" <tr>\n");
sb.append(" <th class=\"tdTitle\" colspan=\"2\">"+m1.get("group")+"</th>\n");
sb.append(" </tr>\n");
List<Map> list2 = (List<Map>) m1.get("params");
for(Map m2:list2) {
sb.append(" <tr>\n");
sb.append(" <td class=\"tdTitle\">"+m2.get("k")+"</td>\n");
sb.append(" <td>"+m2.get("v")+"</td>\n");
sb.append(" </tr>\n");
}
}
sb.append(" </tbody>\n");
sb.append("</table>");
return sb.toString();
}
controller
/**
* 展示规则参数
* @param itemCatId
*/
@RequestMapping("/showitem/{itemId}")
public String showitemParam(@PathVariable long itemId,Model model) {
String itemParam = itemParamService.getItemParamByItemId(itemId);
model.addAttribute("itemParam", itemParam);
return "item";
}
jsp页面
</head>
<body>
${itemParam}
</body>
</html>