移动商城第九篇【属性选项卡、最小存储单元、数据进库】

193 阅读10分钟

tags: 移动商城项目


属性选项卡

第三个选项卡涉及到了我们的手机属性,因此,还是需要用到我们其他的数据库表:EB_FEATURE

继续做逆向工程:

这里写图片描述

查询出普通属性和特殊属性:


  <select id="selectCommFeature" resultMap="BaseResultMap">

    select * from eb_feature t where t.is_spec = 0
  </select>
  <select id="selectSpecFeature" resultMap="BaseResultMap">
    select * from eb_feature t where t.is_spec = 1
  </select>

dao和service和controller

dao实现


/**
 * 继承SqlSessionDaoSupport能够得到sessionFactory的引用,非常方便!
 */
@Repository
public class EbFeatureDaoImpl extends SqlSessionDaoSupport implements EbFeatureDao {

    String nameSpace = "com.rl.ecps.sqlMap.EbFeatureMapper.";

    public List<EbFeature> selectCommFeature() {
        return this.getSqlSession().selectList(nameSpace + "selectCommFeature");
    }

    public List<EbFeature> selectSpecFeature() {
        return this.getSqlSession().selectList(nameSpace + "selectSpecFeature");
    }
}

service实现


@Service
public class EbFeatureServiceImpl implements EbFeatureService {
    
    @Autowired
    private EbFeatureDao featureDao;
    public List<EbFeature> selectCommFeature() {
        return featureDao.selectCommFeature();
    }

    public List<EbFeature> selectSpecFeature() {
        return featureDao.selectSpecFeature();
        
    }
}

controller调用service拿到对应的普通属性和特殊属性。


    /**
     * 跳转到添加商品页面
     *
     * @return
     */
    @RequestMapping("/toAddItem.do")
    public String toAddItem(Model model) {

        List<EbBrand> ebBrands = ebBrandService.selectBrand();
        List<EbFeature> commFeature = featureService.selectCommFeature();
        List<EbFeature> specFeature = featureService.selectSpecFeature();
        model.addAttribute("ebBrands", ebBrands);
        model.addAttribute("commFeature", commFeature);
        model.addAttribute("specFeature", specFeature);

        return "item/addItem";
    }

JSP显示普通属性:

  • forEach标签默认支持遍历以“,”逗号分割的数据!


<div id="tab_3" class="edit set" style="display: none">
    <c:if test="${fn:length(commFeature) == 0}">
        <p><label></label>无属性</p>
    </c:if>

    <%--判断每个属性的录入方式并显示--%>
    <c:forEach items="${commFeature}" var="feature">
        <p>
            <label>${feature.featureName }:</label>
                <%--如果输入类型为1,那么就是下拉框方式--%>
            <c:if test="${feature.inputType==1}">
                <select name="${feature.featureId}">

                    <%--这里需要设置一个空值,否则后台是可以获取到数据“请选择”--%>
                    <option value="">请选择</option>
                    <c:forEach items="${feature.selectValues}" var="value">
                        <option value="${value}">${value}</option>
                    </c:forEach>
                </select>

            </c:if>
                <%--如果输入类型为2,那么就是单选框方式--%>
            <c:if test="${feature.inputType==2}">
                <c:forEach items="${feature.selectValues}" var="value">
                    <input type="radio" name="${feature.featureId}" value="${value}">${value} &nbsp;
                </c:forEach>
            </c:if>

                <%--如果输入类型为3,那么就是多选框方式--%>
            <c:if test="${feature.inputType==3}">
                <c:forEach items="${feature.selectValues}" var="value">
                    <input type="checkbox" name="${feature.featureId}" value="${value}">${value} &nbsp;
                </c:forEach>
            </c:if>
        </p>
    </c:forEach>


</div>

这里写图片描述

属性存放

想要把我们在页面上选定的基本属性进行保存的话,我们是使用另一张表来进行保存的。Featrue表仅仅保存了相对应的属性,是不做保存功能的!

这里写图片描述

因此,我们需要对EB_PARA_VALUE做逆向工程!

这里写图片描述

我们参数表的主键是不需要被其他的表用的, 因此我们直接使用序列来管理进行的。并不需要主键返回


  <insert id="insert" parameterType="com.rl.ecps.model.EbParaValue" >
    insert into EB_PARA_VALUE (PARA_ID, ITEM_ID, FEATURE_ID, 
      PARA_VALUE)
    values (seqparavalueid.nextval, #{itemId,jdbcType=DECIMAL}, #{featureId,jdbcType=DECIMAL},
      #{paraValue,jdbcType=VARCHAR})
  </insert>

编写参数表的dao


public interface EbParaValueDao {


    /**
     *由于我们的参数数据是多个的,不想在service做循环而浪费我们的数据库连接
     * 因此就使用了List集合作为参数
     * @param ebParaValues
     * @param itemId
     */
    void saveParaValue(List<EbParaValue> ebParaValues, Long itemId);

}

@Repository
public class EbParaValueDaoImpl extends SqlSessionDaoSupport implements EbParaValueDao {

    private String nameSpace = "com.rl.ecps.sqlMap.EbParaValueMapper.";
    public void saveParaValue(List<EbParaValue> ebParaValues, Long itemId) {

        //获取数据库连接,通过一个连接把数据存到数据库里边去
        SqlSession sqlSession = this.getSqlSession();
        for (EbParaValue ebParaValue : ebParaValues) {
            ebParaValue.setItemId(itemId);
            sqlSession.insert(nameSpace + "insert", ebParaValue);
        }
    }
}


controller

回到我们的网页上,我们发现属性是非常多的,那么我们在controller是怎么接收的呢???

这里写图片描述

我们将JSP页面的name属性都设置为我们的featureId

这里写图片描述

由于我们该页面上的数据都是从数据库中查询出来的,数据库中的记录有多少,在页面上显示的就有多少

因此,我们可以这么干:

  • 我们使用request对象来获取页面上所有的勾选出来的数据属性
  • 再次从数据库中查询数据,遍历这些数据,如果发现有勾选出来的数据,那么我们就保存在EbParaValue对象中!

代码:


        //查询出所有的属性数据
        List<EbFeature> commFeature = featureService.selectCommFeature();

        //创建一个集合来装载我们所有的参数数据
        List<EbParaValue> ebParaValues = new ArrayList<EbParaValue>();

        for (EbFeature feature : commFeature) {
            //得到录入方式
            Short inputType = feature.getInputType();

            //复选,复选的值是有多个的
            if (inputType == 3) {
                String[] parameterValues = request.getParameterValues(feature.getFeatureId() + "");

                //装载参数数据
                String value = "";

                //如果得到的数据不为null,那么就使用一个字符串来对其进行拼接
                if (parameterValues != null && parameterValues.length > 0) {
                    for (String parameterValue : parameterValues) {
                        value = value + parameterValue + ",";
                    }
                    //去除最后一个逗号
                    value = value.substring(0, value.length() - 1);

                    //把数据封装到参数对象上
                    EbParaValue ebParaValue = new EbParaValue();
                    ebParaValue.setFeatureId(feature.getFeatureId());
                    ebParaValue.setParaValue(value);

                    //装载到集合中
                    ebParaValues.add(ebParaValue);
                }


            }else{
                //非复选的值都只有一个
                String parameter = request.getParameter(feature.getFeatureId() + "");

                //如果拿到的数据不为null
                if (StringUtils.isNotBlank(parameter)) {

                    //把数据封装到参数对象上
                    EbParaValue ebParaValue = new EbParaValue();
                    ebParaValue.setFeatureId(feature.getFeatureId());
                    ebParaValue.setParaValue(parameter);

                    //装载到集合中
                    ebParaValues.add(ebParaValue);
                }
            }
        }

测试:

这里写图片描述

这里写图片描述

最小库存单元选项卡

来到我们的最小库存单元选项卡,我们是需要把我们的特殊属性查询出来的,供用户选择。

查询出特殊属性:

这里写图片描述


<c:forEach items="${specFeature }" var="spec">
    <tr>
        <td>${spec.featureName }:</td>
        <td>
            <c:forEach items="${spec.selectValues}" var="para">
                    <input type="radio" name="${spec.featureId}" value="${para}">${para}
            </c:forEach>
        </td>
    </tr>
</c:forEach>

这里写图片描述

当我们想点击增加规格的时候,就应该多那么一个div在页面上显示!那为什么我们需要多个规格呢??如下所示:

这里写图片描述

对该按钮添加单击事件


    //实现页面规格的自动增加和删除
    $("#button2").click(function () {

        //得到想要控件div所有的内容,不包含自己的标签
        var htmlDiv = $("#sp_0").html();

        //把自己的标签包含进去
        htmlDiv = "<div class='sp_0'>"+htmlDiv+"</div>";

        //在下一个div之前插入
        $(".page_c").before(htmlDiv);

    });

当我们添加了对应的内容时,问题就随之而来了:我们的按钮选项互斥了!

  • 当我们点击第一行的颜色时,想要点击第二行的颜色就不行了!【第一行的颜色选择没有了】
  • 提交表单中的name属性多个重复了。

原因就是出在:

  • name属性是一样的,radio只让选一个!
  • 我们是直接把html内容复制过来的。

那么我们使用一个变量值,让每次的name属性都不一样即可!


    //得到divNum的值
    var divNum =  $("#divNum").val();
    
    //实现页面规格的自动增加和删除
    $("#button2").click(function () {
        divNum++;
        
        //得到想要控件div所有的内容,不包含自己的标签
        var htmlDiv = $("#sp_0").html();
        
       //把自己的标签包含进去
        htmlDiv = "<div class='sp_0' id='sp_"+divNum+"'>"+htmlDiv+"</div>";
        
        //修改各个name的值,使用正则表达式就可以修改一部份的了
        htmlDiv = htmlDiv.replace(/specradio1/g, "specradio"+divNum);
        htmlDiv = htmlDiv.replace(/#sp_0/g, "#sp_"+divNum);
        
        //skuType1   showStatus1   sort1     skuPrice1  marketPrice1  stockInventory1  skuUpperLimit1  sku1  location1
        htmlDiv = htmlDiv.replace(/skuType1/g, "skuType"+divNum);
        htmlDiv = htmlDiv.replace(/showStatus1/g, "showStatus"+divNum);
        htmlDiv = htmlDiv.replace(/sort1/g, "sort"+divNum);
        htmlDiv = htmlDiv.replace(/skuPrice1/g, "skuPrice"+divNum);
        htmlDiv = htmlDiv.replace(/marketPrice1/g, "marketPrice"+divNum);
        htmlDiv = htmlDiv.replace(/stockInventory1/g, "stockInventory"+divNum);
        htmlDiv = htmlDiv.replace(/skuUpperLimit1/g, "skuUpperLimit"+divNum);
        htmlDiv = htmlDiv.replace(/sku1/g, "sku"+divNum);
        htmlDiv = htmlDiv.replace(/location1/g, "location"+divNum);

        //重新设置div的值
        $("#divNum").val(divNum);

        //在下一个div之前插入
        $(".page_c").before(htmlDiv);

    });

还是就是我们不能删除第一个销售单元规格:


        function clickRemove(id) {
            var a = $(".sp_0").length;
            if (a == 1) {
                alert("默认规格不可删除");
                return;
            }
        }

最小库存单元属性存放

我们的最小库存单元涉及到了两张数据库表:

这里写图片描述

首先我们来做逆向工程:

这里写图片描述

设置SKU有一个集合来保存所有的特殊属性值:

	private List<EbSpecValue> specList;

    public List<EbSpecValue> getSpecList() {
        return specList;
    }

    public void setSpecList(List<EbSpecValue> specList) {
        this.specList = specList;
    }

sku的主键需要被SpecValue用到,因此需要返回主键


    <selectKey keyProperty="skuId" order="BEFORE" resultType="long">
      select seqskuid.nextval from dual
    </selectKey>

specValue主键自动增长:


  <insert id="insert" parameterType="com.rl.ecps.model.EbSpecValue" >
    insert into EB_SPEC_VALUE (SPEC_ID, SKU_ID, FEATURE_ID, 
      SPEC_VALUE)
    values (seqspecvalueid.nextval, #{skuId,jdbcType=DECIMAL}, #{featureId,jdbcType=DECIMAL}, 
      #{specValue,jdbcType=VARCHAR})
  </insert>

编写Dao


public interface EbSkuDao {
    
    void saveEbSku(List<EbSku> ebSkus, Long itemId);
    
}



/**
 * 继承SqlSessionDaoSupport能够得到sessionFactory的引用,非常方便!
 */
@Repository
public class EbSkuDaoImpl extends SqlSessionDaoSupport implements EbSkuDao {

    String nameSpace = "com.rl.ecps.sqlMap.EbSkuMapper.";
    String nameSpace1 = "com.rl.ecps.sqlMap.EbSpecValueMapper.";


    public void saveEbSku(List<EbSku> ebSkus, Long itemId) {
        SqlSession sqlSession = this.getSqlSession();
        for (EbSku ebSku : ebSkus) {

            //设置商品属性
            ebSku.setItemId(itemId);

            sqlSession.insert(nameSpace+"insert", ebSku);
            List<EbSpecValue> specList = ebSku.getSpecList();
            for (EbSpecValue ebSpecValue : specList) {
                ebSpecValue.setSkuId(ebSku.getSkuId());
                sqlSession.insert(nameSpace1 + "insert", ebSpecValue);
            }
        }
    }
}

Controller获取页面数据


 //使用集合来进行装sku的对象
        List<EbSku> skuList = new ArrayList<EbSku>();

        //遍历出特殊属性的值
        List<EbFeature> specList = featureService.selectSpecFeature();

        //获取页面有多少个单元格,对其进行遍历,取出对应的值
        for (int i = 1; i <= divNum; i++) {

            //获得商城价和库存,他们是必填的字段
            String skuPrice = request.getParameter("skuPrice" + i);
            String stock = request.getParameter("stockInventory" + i);

            //如果上面的必填字段不是空说明数据有效
            if (StringUtils.isNotBlank(skuPrice) && StringUtils.isNotBlank(stock)) {

                String skuType = request.getParameter("skuType" + i);
                String showStatus = request.getParameter("showStatus" + i);
                String sort = request.getParameter("sort" + i);
                String marketPrice = request.getParameter("marketPrice" + i);
                String skuUpperLimit = request.getParameter("skuUpperLimit" + i);
                String sku = request.getParameter("sku" + i);
                String location = request.getParameter("location" + i);

                //创建最小销售单元的对象,并且赋值
                EbSku skuObj = new EbSku();
                skuObj.setSkuPrice(new BigDecimal(skuPrice));
                skuObj.setStockInventory(new Integer(stock));

                if (StringUtils.isNotBlank(skuType) && !StringUtils.equals(skuType, "")) {
                    skuObj.setSkuType(new Short(skuType));
                }
                if (StringUtils.isNotBlank(showStatus) && !StringUtils.equals(showStatus, "")) {
                    skuObj.setShowStatus(new Short(showStatus));
                }
                if (StringUtils.isNotBlank(sort) && !StringUtils.equals(sort, "")) {
                    skuObj.setSkuSort(new Integer(sort));
                }
                if (StringUtils.isNotBlank(marketPrice) && !StringUtils.equals(marketPrice, "")) {
                    skuObj.setMarketPrice(new BigDecimal(marketPrice));
                }
                if (StringUtils.isNotBlank(skuUpperLimit) && !StringUtils.equals(skuUpperLimit, "")) {
                    skuObj.setSkuUpperLimit(new Integer(skuUpperLimit));
                }
                skuObj.setSku(sku);
                skuObj.setLocation(location);

                //装取特殊属性的集合
                List<EbSpecValue> specValList = new ArrayList<EbSpecValue>();

                for (EbFeature feature : specList) {
                    Long featureId = feature.getFeatureId();
                    //获得所选规格属性的值
                    String specVal = request.getParameter(featureId + "specradio" + i);
                    if (StringUtils.isNotBlank(specVal)) {
                        //创建规格对象
                        EbSpecValue spec = new EbSpecValue();
                        spec.setFeatureId(featureId);
                        spec.setSpecValue(specVal);
                        specValList.add(spec);
                    }
                }
                skuObj.setSpecList(specValList);
                skuList.add(skuObj);
            }
        }

获取得到值:

这里写图片描述

将Item数据存进数据库

到目前为止,我们4个选项卡的数据都可以拿到了。因此,我们可以把Item所需要的对象存入数据库了..

dao层编写


    public void saveItem(EbItem ebItem) {
        this.getSqlSession().insert(nameSpace + "insert", ebItem);
    }

service层编写:


    public void saveItem(EbItem ebItem, EbItemClob clob, List<EbSku> skus, List<EbParaValue> ebParaValues) {
        itemDao.saveItem(ebItem);

        clobDao.saveItemClob(clob, ebItem.getItemId());

        skuDao.saveEbSku(skus, ebItem.getItemId());

        paraValueDao.saveParaValue(ebParaValues, ebItem.getItemId());
    }

controller编写:


 @RequestMapping("/addItem.do")
    public void addItem(EbItem ebItem, EbItemClob ebItemClob, HttpServletRequest request, Integer divNum) {


        //为商品设置编号
        ebItem.setItemNo(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()));

        //查询出所有的属性数据
        List<EbFeature> commFeature = featureService.selectCommFeature();

        //创建一个集合来装载我们所有的参数数据
        List<EbParaValue> ebParaValues = new ArrayList<EbParaValue>();

        for (EbFeature feature : commFeature) {
            //得到录入方式
            Short inputType = feature.getInputType();

            //复选,复选的值是有多个的
            if (inputType == 3) {
                String[] parameterValues = request.getParameterValues(feature.getFeatureId() + "");

                //装载参数数据
                String value = "";

                //如果得到的数据不为null,那么就使用一个字符串来对其进行拼接
                if (parameterValues != null && parameterValues.length > 0) {
                    for (String parameterValue : parameterValues) {
                        value = value + parameterValue + ",";
                    }
                    //去除最后一个逗号
                    value = value.substring(0, value.length() - 1);

                    //把数据封装到参数对象上
                    EbParaValue ebParaValue = new EbParaValue();
                    ebParaValue.setFeatureId(feature.getFeatureId());
                    ebParaValue.setParaValue(value);

                    //装载到集合中
                    ebParaValues.add(ebParaValue);
                }

            } else {
                //非复选的值都只有一个
                String parameter = request.getParameter(feature.getFeatureId() + "");

                //如果拿到的数据不为null
                if (StringUtils.isNotBlank(parameter)) {

                    //把数据封装到参数对象上
                    EbParaValue ebParaValue = new EbParaValue();
                    ebParaValue.setFeatureId(feature.getFeatureId());
                    ebParaValue.setParaValue(parameter);

                    //装载到集合中
                    ebParaValues.add(ebParaValue);
                }
            }
        }

        //使用集合来进行装sku的对象
        List<EbSku> skuList = new ArrayList<EbSku>();

        //遍历出特殊属性的值
        List<EbFeature> specList = featureService.selectSpecFeature();

        //获取页面有多少个单元格,对其进行遍历,取出对应的值
        for (int i = 1; i <= divNum; i++) {

            //获得商城价和库存,他们是必填的字段
            String skuPrice = request.getParameter("skuPrice" + i);
            String stock = request.getParameter("stockInventory" + i);

            //如果上面的必填字段不是空说明数据有效
            if (StringUtils.isNotBlank(skuPrice) && StringUtils.isNotBlank(stock)) {

                String skuType = request.getParameter("skuType" + i);
                String showStatus = request.getParameter("showStatus" + i);
                String sort = request.getParameter("sort" + i);
                String marketPrice = request.getParameter("marketPrice" + i);
                String skuUpperLimit = request.getParameter("skuUpperLimit" + i);
                String sku = request.getParameter("sku" + i);
                String location = request.getParameter("location" + i);

                //创建最小销售单元的对象,并且赋值
                EbSku skuObj = new EbSku();
                skuObj.setSkuPrice(new BigDecimal(skuPrice));
                skuObj.setStockInventory(new Integer(stock));

                if (StringUtils.isNotBlank(skuType) && !StringUtils.equals(skuType, "")) {
                    skuObj.setSkuType(new Short(skuType));
                }
                if (StringUtils.isNotBlank(showStatus) && !StringUtils.equals(showStatus, "")) {
                    skuObj.setShowStatus(new Short(showStatus));
                }
                if (StringUtils.isNotBlank(sort) && !StringUtils.equals(sort, "")) {
                    skuObj.setSkuSort(new Integer(sort));
                }
                if (StringUtils.isNotBlank(marketPrice) && !StringUtils.equals(marketPrice, "")) {
                    skuObj.setMarketPrice(new BigDecimal(marketPrice));
                }
                if (StringUtils.isNotBlank(skuUpperLimit) && !StringUtils.equals(skuUpperLimit, "")) {
                    skuObj.setSkuUpperLimit(new Integer(skuUpperLimit));
                }
                skuObj.setSku(sku);
                skuObj.setLocation(location);

                //装取特殊属性的集合
                List<EbSpecValue> specValList = new ArrayList<EbSpecValue>();

                for (EbFeature feature : specList) {
                    Long featureId = feature.getFeatureId();
                    //获得所选规格属性的值
                    String specVal = request.getParameter(featureId + "specradio" + i);
                    if (StringUtils.isNotBlank(specVal)) {
                        //创建规格对象
                        EbSpecValue spec = new EbSpecValue();
                        spec.setFeatureId(featureId);
                        spec.setSpecValue(specVal);
                        specValList.add(spec);
                    }
                }
                skuObj.setSpecList(specValList);
                skuList.add(skuObj);
            }
        }
        itemService.saveItem(ebItem, ebItemClob, skuList, ebParaValues);
        return "redirect:listItem.do";
    }

检查数据是否进去了

  • 项目的id是自己查询出来的。

SELECT * from EB_ITEM WHERE ITEM_ID = 3073
SELECT  * from EB_SKU where ITEM_ID = 3073
SELECT * from EB_PARA_VALUE WHERE ITEM_ID =  3073

SELECT  * from EB_SPEC_VALUE WHERE SKU_ID = 3060

#总结 #

  • 第三个选项卡是展示商品的普通属性字段的,拿到数据库的所有普通属性字段,在页面上判断输入的方式是哪一个,按照不同的输入方式来展示(有的下拉框、有的多选框、有的单选框)
  • 展示完之后,那我们怎么获取选中的数据呢???页面上又有下拉框、又有多选框什么的。单单通过**字符串数据的方式获取选中的数据是不行的。**因为我们无法判断该属性是哪种输入方式。
    • 我们可以这样干:页面展示的数据都是我们后台查询出来的。那么我们只要遍历原来的集合,获取选中的Id。
    • 在遍历期间判断输入方式,如果是多选框,那我们就获取其字符串数组、如果是单选框、那么就直接获取其id。
    • 只要id吻合了,那么就是页面选中的数据。只要将被选中的数据封装到对象中。
  • 当然了,一个商品也是有很多参数的,在Dao层用集合来进行保存所有的参数,商品的Id也是需要外界传递进来的。用一个Session就要把所有的数据存入到数据库中。
  • 对于最小销售单元,我们查询出特殊的属性在页面上展示。可能需要多个规格,可以使用Jquery来进行复制。
    • 复制出来是会有问题的:name属性的名字是相同的,于是一个规格和第二个规格就会互斥、我们后台也不能拿到数据
    • 既然知道根本的原因是name属性,我们只要在复制后,改变name属性的名称即可。我们通过一个变量,既可以记录我们增添了多少个规格,又可以用来标识不同的name属性
    • 在复制完之后,使用正则表达式把对应的name名称替换即可了。
  • 一个商品也对应着多个销售单元的,因此还是用集合来进行保存。同样需要外界对商品的Id传入。由于Sku和SkuValue需要同时在页面上展示,那么Sku还是需要使用List来维护SkuValue的。
  • 在保存Sku时和ParaValue的逻辑是差不多的。

如果您觉得这篇文章帮助到了您,可以给作者一点鼓励