概述
上一篇博文 实战SSM_O2O商铺_25【商品类别】商品类别列表展示从Dao到View层的开发 ,我们完成了 商品类别 列表展示的开发,接下来,我们继续来完成 【批量添加商品类别】的功能吧。
Dao层
ProductCategoryDao接口
/** * * * @Title: batchInsertProductCategory * * @Description: 批量增加roductCategory * * @param productCategoryList * * @return: int */ int batchInsertProductCategory(List<ProductCategory> productCategoryList);
ProductCategoryDao SQL映射文件
<insert id="batchInsertProductCategory" parameterType="java.util.List"> INSERT INTO tb_product_category( product_category_name, product_category_desc, priority, create_time, last_edit_time, shop_id) VALUES <foreach collection="list" item="productCategory" index="index" separator=","> ( #{productCategory.productCategoryName}, #{productCategory.productCategoryDesc}, #{productCategory.priority}, #{productCategory.createTime}, #{productCategory.lastEditTime}, #{productCategory.shopId} ) </foreach> </insert>
单元测试
@Test public void testBatchInsertProductCategory() { ProductCategory productCategory1 = new ProductCategory(); productCategory1.setProductCategoryName("ProductCategoryTest1"); productCategory1.setProductCategoryDesc("ProductCategoryTest1-desc"); productCategory1.setPriority(300); productCategory1.setCreateTime(new Date()); productCategory1.setLastEditTime(new Date()); productCategory1.setShopId(5L); ProductCategory productCategory2 = new ProductCategory(); productCategory2.setProductCategoryName("ProductCategoryTest2"); productCategory2.setProductCategoryDesc("ProductCategoryTest2-desc"); productCategory2.setPriority(600); productCategory2.setCreateTime(new Date()); productCategory2.setLastEditTime(new Date()); productCategory2.setShopId(5L); List<ProductCategory> productCategoryList = new ArrayList<ProductCategory>(); productCategoryList.add(productCategory1); productCategoryList.add(productCategory2); int effectNum = productCategoryDao.batchInsertProductCategory(productCategoryList); Assert.assertEquals(2, effectNum); }
单元测试OK。
Service层
ProductCategoryExecution DTO类的开发
我们需要增加操作的状态及数量等信息,因此单独的Domain类已经无法满足需求了,因此我们使用DTO来扩展实体类的功能
package com.artisan.o2o.dto; import java.util.List; import com.artisan.o2o.entity.ProductCategory; import com.artisan.o2o.enums.ProductCategoryStateEnum; /** * * * @ClassName: ProductCategoryExecution * * @Description: 封装操作ProductCategory的返回结果,包括操作状态和ProductCategory信息 * * @author: Mr.Yang * * @date: 2018年6月21日 上午12:17:07 */ public class ProductCategoryExecution { private int state; private String stateInfo; // 因为是批量操作,所以使用List private List<ProductCategory> productCategoryList; private int count; /** * * * @Title:ProductCategoryExecution * * @Description:空的构造函数 */ public ProductCategoryExecution() { super(); } /** * * * @Title:ProductCategoryExecution * * @Description:操作成功的时候使用的构造函数,返回操作状态和ProductCategory集合 * * @param productCategoryStateEnum * @param productCategoryList * @param count */ public ProductCategoryExecution(ProductCategoryStateEnum productCategoryStateEnum, List<ProductCategory> productCategoryList, int count) { this.state = productCategoryStateEnum.getState(); this.stateInfo = productCategoryStateEnum.getStateInfo(); this.productCategoryList = productCategoryList; this.count = count; } /** * * * @Title:ProductCategoryExecution * * @Description:操作失败的时候返回的信息,仅包含状态和状态描述即可 * * @param productCategoryStateEnum */ public ProductCategoryExecution(ProductCategoryStateEnum productCategoryStateEnum) { this.state = productCategoryStateEnum.getState(); this.stateInfo = productCategoryStateEnum.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; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
ProductCategoryStateEnum 增加几个标识
SUCCESS(1, "操作成功"), INNER_ERROR(-1001, "操作失败"), NULL_SHOP(-1002, "Shop信息为空"), EMPETY_LIST(-1003, "请输入商品目录信息");
封装特定异常类
批量添加,这里我们使用事务控制
package com.artisan.o2o.exception; /** * * * @ClassName: ProductCategoryOperationException * * @Description: 继承RuntimeException,便于异常时候的回滚。 保持所有的操作在一个事务中。 * * 这样在标注了@Transactional事务的方法中,出现了异常,才会回滚数据。 * * 默认情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常)或者 Error,则 Spring * 将回滚事务;除此之外,Spring 不会回滚事务。 * * * @author: Mr.Yang * * @date: 2018年6月21日 上午12:22:44 */ public class ProductCategoryOperationException extends RuntimeException { private static final long serialVersionUID = 6500682256313143297L; public ProductCategoryOperationException(String message) { super(message); } }
ProductCategoryService接口
/** * * * @Title: addProductCategory * * @Description: 批量插入ProductCategory * * @param productCategoryList * @throws ProductCategoryOperationException * * @return: ProductCategoryExecution */ ProductCategoryExecution addProductCategory(List<ProductCategory> productCategoryList) throws ProductCategoryOperationException;
ProductCategoryServiceImpl实现类
/** * 使用@Transactional控制事务 */ @Override @Transactional public ProductCategoryExecution addProductCategory(List<ProductCategory> productCategoryList) throws ProductCategoryOperationException { // 非空判断 if (productCategoryList != null && productCategoryList.size() > 0) { try { // 批量增加ProductCategory int effectNum = productCategoryDao.batchInsertProductCategory(productCategoryList); if (effectNum > 0) { return new ProductCategoryExecution(ProductCategoryStateEnum.SUCCESS, productCategoryList, effectNum); } else { return new ProductCategoryExecution(ProductCategoryStateEnum.INNER_ERROR); } } catch (Exception e) { e.printStackTrace(); throw new ProductCategoryOperationException("batchAddProductCategory Error:" + e.getMessage()); } } else { return new ProductCategoryExecution(ProductCategoryStateEnum.EMPETY_LIST); } }
单元测试
@Test public void testAddProductCategory() { ProductCategory productCategory1 = new ProductCategory(); productCategory1.setProductCategoryName("ProductCategoryTest3"); productCategory1.setProductCategoryDesc("ProductCategoryTest3-desc"); productCategory1.setPriority(300); productCategory1.setCreateTime(new Date()); productCategory1.setLastEditTime(new Date()); productCategory1.setShopId(5L); ProductCategory productCategory2 = new ProductCategory(); productCategory2.setProductCategoryName("ProductCategoryTest4"); productCategory2.setProductCategoryDesc("ProductCategoryTest4-desc"); productCategory2.setPriority(600); productCategory2.setCreateTime(new Date()); productCategory2.setLastEditTime(new Date()); productCategory2.setShopId(5L); List<ProductCategory> productCategoryList = new ArrayList<ProductCategory>(); productCategoryList.add(productCategory1); productCategoryList.add(productCategory2); ProductCategoryExecution productCategoryExecution = productCategoryService.addProductCategory(productCategoryList); Assert.assertEquals(1, productCategoryExecution.getState()); Assert.assertEquals(2, productCategoryExecution.getProductCategoryList().size()); }
单元测试通过。
Controller层
ProductCategoryController增加addProductCategory方法
/** * * * @Title: addProductCategory * * @Description: 添加商铺目录 ,使用@RequestBody接收前端传递过来的productCategoryList * * @param productCategoryList * @param request * * @return: Map<String,Object> */ @RequestMapping(value = "/addproductcategory", method = RequestMethod.POST) @ResponseBody public Map<String, Object> addProductCategory(@RequestBody List<ProductCategory> productCategoryList, HttpServletRequest request) { Map<String, Object> modelMap = new HashMap<String, Object>(); if (productCategoryList != null && productCategoryList.size() > 0) { // 从session中获取shop的信息 Shop currentShop = (Shop) request.getSession().getAttribute("currentShop"); if (currentShop != null && currentShop.getShopId() != null) { // 为ProductCategory设置shopId for (ProductCategory productCategory : productCategoryList) { productCategory.setShopId(currentShop.getShopId()); } try { // 批量插入 ProductCategoryExecution pce = productCategoryService.addProductCategory(productCategoryList); if (pce.getState() == ProductCategoryStateEnum.SUCCESS.getState()) { modelMap.put("success", true); // 同时也将新增成功的数量返回给前台 modelMap.put("effectNum", pce.getCount()); } else { modelMap.put("success", false); modelMap.put("errMsg", pce.getStateInfo()); } } catch (ProductCategoryOperationException e) { e.printStackTrace(); modelMap.put("success", false); modelMap.put("errMsg", e.getMessage()); return modelMap; } } else { modelMap.put("success", false); modelMap.put("errMsg", ProductCategoryStateEnum.NULL_SHOP.getStateInfo()); } } else { modelMap.put("success", false); modelMap.put("errMsg", "至少输入一个店铺目录信息"); } return modelMap; }
单元测试
待前端页面完成,一并测试
View层
productcategorymanage.js
$(function () { // 后台从session中获取shop的信息,这里就不传shopId了 //var shopId = getQueryString("shopId"); //var productCategoryURL = '/o2o/shopadmin/getproductcategorybyshopId?shopId=' + shopId; var getProductCategoryURL = '/o2o/shopadmin/getproductcategorybyshopId'; var addProductCategoryURL = '/o2o/shopadmin/addproductcategory'; // 调用getProductCategoryList,加载数据 getProductCategoryList(); function getProductCategoryList() { $.getJSON(getProductCategoryURL, function(data) { if (data.success) { var dataList = data.data; $('.product-categroy-wrap').html(''); var tempHtml = ''; dataList .map(function(item, index) { tempHtml += '' + '<div class="row row-product-category now">' + '<div class="col-33 product-category-name">' + item.productCategoryName + '</div>' + '<div class="col-33">' + item.priority + '</div>' + '<div class="col-33"><a href="#" class="button delete" data-id="' + item.productCategoryId + '">删除</a></div>' + '</div>'; }); $('.product-categroy-wrap').append(tempHtml); } }); } // 新增按钮的点击事件 $('#new').click( function(){ // 新增数据 以 temp 为标识,便于和库表中的数据区分开来 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>'; $('.product-categroy-wrap').append(tempHtml); }); $('#submit').click(function() { // 通过temp 获取新增的行 var tempArr = $('.temp'); // 定义数组接收新增的数据 var productCategoryList = []; tempArr.map(function(index, item) { var tempObj = {}; tempObj.productCategoryName = $(item).find('.category').val(); tempObj.priority = $(item).find('.priority').val(); if (tempObj.productCategoryName && tempObj.priority) { productCategoryList.push(tempObj); } }); $.ajax({ url : addProductCategoryURL, type : 'POST', // 后端通过 @HttpRequestBody直接接收 data : JSON.stringify(productCategoryList), contentType : 'application/json', success : function(data) { if (data.success) { $.toast('新增【' + data.effectNum + '】条成功!'); // 重新加载数据 getProductCategoryList(); } else { $.toast(data.errMsg); } } }); }); });
前后端联调
前端页面debug, 后端也可以加入断点,以debug的方式开启tomcat,逐步调测
效果如下:
库表数据:
Github地址
代码地址: https://github.com/yangshangwei/o2o