商品类别增删查

商品类别:
首先往数据库的商品类别表添加数据,以便进行测试。
实体类


image.png

然后编写dao层


image.png

mapper实现dao
image.png

junit测试dao
image.png

编写service


image.png

image.png

编写controller层
我们可以用modelMap,StringObject来表示方法的返回值,但是由于我们这里只返回一个对象,所以我们换一种知识,使用Result把json封装起来去返回,在dto里编写result类,跟shopExecution差不多,只不过它是泛型。
package com.imooc.o2o.dto;

/**
 * 封装json对象,所有返回结果都使用它
 *
 */
public class Result<T> {
    private boolean success;// 是否成功标志
    private T data;// 成功时返回的数据
    private String errorMsg;// 错误信息
    private int errorCode;// 错误码

    public Result() {

    }

    // 成功时的构造器
    public Result(boolean success, T data) {
        this.success = success;
        this.data = data;
    }

    // 错误时的构造器
    public Result(boolean success, String errorMsg, int errorCode) {
        this.success = success;
        this.errorMsg = errorMsg;
        this.errorCode = errorCode;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public int getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }

}

再回去编写controller


image.png

image.png

在这之前得编写枚举类

package com.imooc.o2o.enums;

public enum ProductCategoryStateEnum {
    OFFLINE(-1, "非法商品类别"), SUCCESS(1, "操作成功"), PASS(2, "通过认证"), INNER_ERROR(-1001,
            "内部系统错误"), NULL_SHOPID(-1002, "ShopId为空"), NULL_PRODUCTCATEGORY(-1003, "productcategory信息为空");

    private int state;
    private String stateInfo;

    // 枚举被设计为单例模式
    private ProductCategoryStateEnum(int state, String stateInfo) {
        this.state = state;
        this.stateInfo = stateInfo;
    }

    /**
     * 根据state返回相应的enum
     * 
     * @param state
     * @return
     */
    public ProductCategoryStateEnum stateOf(int state) {
        for (ProductCategoryStateEnum stateEnum : values()) {
            if (stateEnum.state == state)
                return stateEnum;
        }
        return null;
    }

    public int getState() {
        return state;
    }

    public String getStateInfo() {
        return stateInfo;
    }
    
    
}

然后debug启动tomcat,浏览器输入
http://localhost:8080/o2o/shopadmin/getproductcategorylist
会发现类别并没有按priority从高到低排列,因为我们sql语句没有orderby

image.png

等一会刷新页面就行了。
商品类别列表前端
商品类别列表的controller方法里的模拟登录可以去掉,因为我们商品类别管理是从商品管理页面跳转过来,session中已经存在shopId了。
image.png

批量添加商品类别

批量所以参数是List
dao层

/**
     * 批量添加商品类别
     * @param productCategoryList
     * @return
     */
    int batchInsertProductCategory(List<ProductCategory> productCategoryList);

实现
参数是List类型,mybatis的循环跟java语法差不多,其中list和productCategory可以自己取名字,就是一productCategory变量名去遍历list,index是计数器,我也不清楚这个是什么意思,index++呢?我把它去掉,ut还是测试成功的,然后sql语句values后是用逗号连接的,例如Value(xxx,xxx),(xxxx,xxx),所以separator是逗号。

<insert id="batchInsertProductCategory" parameterType="java.util.List">
        INSERT INTO
        tb_product_category(product_category_name, priority,
        create_time, shop_id)
        VALUES
        <foreach collection="list" item="productCategory" index="index"
            separator=",">
            (
            #{productCategory.productCategoryName},
            #{productCategory.priority},
            #{productCategory.createTime},
            #{productCategory.shopId}
            )
        </foreach>
    </insert>

service层


image.png

在dto里实现返回类型

public class ProductCategoryExecution {

    // 结果状态
    private int state;
    // 结果标识
    private String stateInfo;
    
    private List<ProductCategory> productCategoryList;
    
    public ProductCategoryExecution() {
        
    }
    
    //操作成功时使用的构造函数
    public ProductCategoryExecution(ProductCategoryStateEnum stateEnum, List<ProductCategory> productCategoryList) {
        this.state = stateEnum.getState();
        this.stateInfo = stateEnum.getStateInfo();
        this.productCategoryList = productCategoryList;
    }
    
    //操作失败时使用的构造函数
    public ProductCategoryExecution(ProductCategoryStateEnum stateEnum) {
        this.state = stateEnum.getState();
        this.stateInfo = stateEnum.getStateInfo();
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

    public void setStateInfo(String stateInfo) {
        this.stateInfo = stateInfo;
    }

    public List<ProductCategory> getProductCategoryList() {
        return productCategoryList;
    }

    public void setProductCategoryList(List<ProductCategory> productCategoryList) {
        this.productCategoryList = productCategoryList;
    }
    
}

在定义exception
这里要注意序列号的与前面的exception不同,选择生成序列号而不是默认序列号。


image.png

最后实现,前面dao测试,这里不测试

    @Override
    public ProductCategoryExecution batchAddProductCategory(List<ProductCategory> productCategoryList)
            throws ProductCategoryOperationException {
        if (productCategoryList != null && productCategoryList.size() > 0) {
            try {
                int effectedNum = productCategoryDao.batchInsertProductCategory(productCategoryList);
                if (effectedNum <= 0) {
                    throw new ProductCategoryOperationException("店铺类别创建失败");
                } else {
                    return new ProductCategoryExecution(ProductCategoryStateEnum.SUCCESS);
                }
            } catch (Exception e) {
                throw new ProductCategoryOperationException("batchAddProductCategory error:" + e.getMessage());
            }

        } else {
            return new ProductCategoryExecution(ProductCategoryStateEnum.EMPTY_LIST);
        }
    }

controller层


image.png

image.png
添加商品类别前端开发

首先看下效果图,点击添加就会自动生成一行可以编辑的


image.png

所以我们需要在js代码里编写一个方法,首先给新增按钮一个id,当点击新增按钮就调用方法,自动生成一行,


image.png
$('#new')
            .click(
                    function() {
                        var tempHtml = '<div class="row row-product-category temp">'
                                + '<div class="col-33"><input class="category-input category" type="text" placeholder="分类名"></div>'
                                + '<div class="col-33"><input class="category-input priority" type="number" placeholder="优先级"></div>'
                                + '<div class="col-33"><a href="#" class="button delete">删除</a></div>'
                                + '</div>';
                        $('.category-wrap').append(tempHtml);
                    });

可以看到我们新生成的行的class最后是temp,而之前的都是now,因为当我们点击提交的时候,只需要获取新添加的,所以就是通过class来区分


image.png

之后就是提交按钮了,获取class为temp的行,然后map遍历添加到与后端规定好的productCategoryList中


image.png

最后再使用ajax提交到后台,其中addUrl是上面写好的url,然后使用json.stringify把数据变成字符串提交到后台


image.png

开始测试,首先debug启动tomcat,在controller里设置断点,从shoplist进去这样才能获取currentShop,新增两个,然后点击提交之前先f12,在提交方法设置断点


image.png

之后点击提交,f10调试下一行,确认有值之后按f8直接调到后台debug,下一步之后,就可以看到前台已经添加进来了
image.png

这里需要注意一下,为什么提交创建的商品类别之后,它的顺序就能立马更新过来呢?原因是我们在ajax里重新调用了getList方法。

商品类别的删除功能

dao层,因为传入两个参数,mybatis不认识所以我们需要param注解

/**
     * 删除指定商品类别
     * @param productCategoryId
     * @param shopId
     * @return
     */
    int deleteProductCategory(@Param("productCategoryId") long productCategoryId, @Param("shopId") long shopId);

dao实现,这里使用注解,所以不用设置参数类型,我们不仅要判断商品类别id是否相同还要判断商店id是否相同,为了更安全的控制,就是你的店铺信息得对才能删除,为了预防删除了不是本店铺的商品类别id,就不好了。

<delete id="deleteProductCategory">
        DELETE FROM
        tb_product_category
        WHERE
        product_category_id = #{productCategoryId}
        AND shop_id = #{shopId}
    </delete>

ut测试


image.png

这里我们的effected是在循环里面的,所以每次都只是一条。所以ass是1而不是遍历的数量。
这里注意,我们可以使用ignore注解去把上面的插入和查询都忽略掉,因为test测试是随机测试的,但是当我们想三个同时测试,因为我们测试了删除,想再重新测试添加就得去删掉ignore,比较麻烦,有什么三个方法按顺序测试吗?就是插入,查询,然后再删除,构成测试循环,我们可以这样做,并且在测试方法名字使用ABC来安排测试顺序


image.png

image.png

image.png

image.png

可以看到无论你测多少次调用顺序都是一样的,并且这样数据库没有任何影响,形成回环。


image.png

service
如果该商品类别下有商品,需要先把商品的商品类别id设置为空
/**
     * 将此类别下的商品里的类别id设置为空,再删除该商品类别
     * @param productCategoryId
     * @param shopId
     * @return
     * @throws ProductCategoryOperationException
     */
    ProductCategoryExecution deleteProductCategory(long productCategoryId, long shopId)
    throws ProductCategoryOperationException;

实现,因为我们这里是有两步要操作的,所以需要事务@Transactional,第一步就是把商品的商品类别id设为空,第二步是删除商品类别,两步都成功才执行,任何一步出错都回滚。


image.png

controller
这里参数Long productategoryId如果写成long下面!=null是会报错的,原因是Long是long的包装类,Long是对象才能判断null,而long是0做判断


image.png

image.png

前端
删除我们分两种,一种是数据库里的,一种是海没存入数据库里的,那么当点击删除按钮的时候怎么区分是调用那个方法呢,答案还是通过class,结果按钮class和列的class就行了


image.png

所以我们的js代码需要写两个删除方法
image.png

image.png

接着测试跟前面一样。这里我们删除数据库里的数据会发现没删掉,报错,原因是我们的js代码里多了个shopId:shopId,但是我们的controll方法参数只有productCategoryId而没有shopId。可以在方法加这个参数,或者在js里去掉,但是后面肯定是要加上的,安全性。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,301评论 8 265
  • “阳光照在他们的身后,画出两条影子,其中一条影子显然是谦卑之态,可是当你换上一个角度,却总是似乎看到两个动物似的影...
    书海识途阅读 394评论 0 0
  • 小时候对于生死的概念大抵是 铺天的白色,半假半真的哭腔,披麻戴孝的人群,红衣服的鼓号队,还有沿着白线可以寻到的丧事...
    66是一枚橙色好的金子阅读 449评论 0 2
  • 这几日沟通一个客户,着实让我着急,当然现在的客人更喜欢钻石的品质,石头的价格,不过,这在如今的中国已经不存在了,因...
    界辉阅读 325评论 0 0