文章目录
- 概述
- 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