实战SSM_O2O商铺_26【商品类别】批量新增商品类别从Dao到View层的开发

2021-08-17 11:32:59 浏览数 (1)

文章目录

  • 概述
  • Dao层
    • ProductCategoryDao接口
    • ProductCategoryDao SQL映射文件
    • 单元测试
  • Service层
    • ProductCategoryExecution DTO类的开发
    • ProductCategoryStateEnum 增加几个标识
    • 封装特定异常类
    • ProductCategoryService接口
    • ProductCategoryServiceImpl实现类
    • 单元测试
  • Controller层
    • ProductCategoryController增加addProductCategory方法
    • 单元测试
  • View层
    • productcategorymanage.js
  • 前后端联调
  • Github地址

概述

上一篇博文 实战SSM_O2O商铺_25【商品类别】商品类别列表展示从Dao到View层的开发 ,我们完成了 商品类别 列表展示的开发,接下来,我们继续来完成 【批量添加商品类别】的功能吧。


Dao层

ProductCategoryDao接口

代码语言:javascript复制
/**
	 * 
	 * 
	 * @Title: batchInsertProductCategory
	 * 
	 * @Description: 批量增加roductCategory
	 * 
	 * @param productCategoryList
	 * 
	 * @return: int
	 */
	int batchInsertProductCategory(List<ProductCategory> productCategoryList);

ProductCategoryDao SQL映射文件

代码语言:javascript复制
<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>

单元测试

代码语言:javascript复制
@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来扩展实体类的功能

代码语言:javascript复制
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 增加几个标识

代码语言:javascript复制
SUCCESS(1, "操作成功"), INNER_ERROR(-1001, "操作失败"), NULL_SHOP(-1002, "Shop信息为空"), EMPETY_LIST(-1003, "请输入商品目录信息");

封装特定异常类

批量添加,这里我们使用事务控制

代码语言:javascript复制
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接口

代码语言:javascript复制
/**
	 * 
	 * 
	 * @Title: addProductCategory
	 * 
	 * @Description: 批量插入ProductCategory
	 * 
	 * @param productCategoryList
	 * @throws ProductCategoryOperationException
	 * 
	 * @return: ProductCategoryExecution
	 */
	ProductCategoryExecution addProductCategory(List<ProductCategory> productCategoryList) throws ProductCategoryOperationException;

ProductCategoryServiceImpl实现类

代码语言:javascript复制
/**
	 * 使用@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);
		}
	}

单元测试

代码语言:javascript复制
@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方法

代码语言:javascript复制
/**
	 * 
	 * 
	 * @Title: addProductCategory
	 * 
	 * @Description: 添加商铺目录 ,使用@RequestBody接收前端传递过来的productCategoryList
	 * 
	 * @param productCategoryList
	 * @param request
	 * 
	 * @return: Map
	 */
	@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

代码语言:javascript复制
$(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  = ''
												  ''
												  ''
												  item.productCategoryName
												  ''
												  ''
												  item.priority
												  ''
												  '  item.productCategoryId
												  '">删除'
												  '';
									});
							$('.product-categroy-wrap').append(tempHtml);
						}
					});
	}
	
    
    
    //  新增按钮的点击事件
    $('#new').click(
    		function(){
    			// 新增数据 以 temp 为标识,便于和库表中的数据区分开来
    			var tempHtml = ''
					  ''
					  ''
					  '删除'
					  '';
    			$('.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

0 人点赞