校园商铺-7商品类别模块-5商品类别删除后端开发
1.Dao层
1.1Dao接口
package com.csj2018.o2o.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.csj2018.o2o.entity.ProductCategory;
public interface ProductCategoryDao {
/**
* 查询某个店铺下的商品分类
* @param shopId
* @return
*/
List<ProductCategory> queryProductCategoryList(long shopId);
/**
* 批量添加商品分类
* @param productCategoryList
* @return
*/
int batchInsertProductCategory(List<ProductCategory> productCategoryList);
/**
* 7-5新增 删除商品类别。由于是2个参数,mybatis认不出来,必须用@Param注解来表明它的参数名
* @param productCategoryId
* @param shopId
* @return
*/
int deleteProductCategory(@Param("productCategoryId")long productCategoryId,@Param("shopId")long shopId);
}
问题:用productCategoryId就可以确认唯一的productCategory。为什么还要加shopId?
目的:要做更安全的控制。需要店铺id和商品类别id同时正确,才能删除。
1.2 mapper文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.csj2018.o2o.dao.ProductCategoryDao">
<select id="queryProductCategoryList" resultType="com.csj2018.o2o.entity.ProductCategory" parameterType="Long">
SELECT
product_category_id,
product_category_name,
priority,
create_time,
shop_id
from tb_product_category
where
shop_id = #{shopId}
order by priority desc
</select>
<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>
<delete id="deleteProductCategory">
delete from tb_product_category where product_category_id = #{productCategoryId} and shop_id =${shopId}
</delete>
</mapper>
1.3 单元测试
package com.csj2018.o2o.dao;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.csj2018.o2o.BaseTest;
import com.csj2018.o2o.entity.ProductCategory;
public class ProductCategoryDaoTest extends BaseTest {
@Autowired
private ProductCategoryDao productCategoryDao;
...
//7-5新增
@Test
public void testDeleteProductCategory() {
long shopId = 1;
List<ProductCategory> productCategoryList = productCategoryDao.queryProductCategoryList(shopId);
for(ProductCategory pc:productCategoryList) {
if("批量插入商品类别1".equals(pc.getProductCategoryName())||"批量插入商品类别2".equals(pc.getProductCategoryName())) {
int count = productCategoryDao.deleteProductCategory(pc.getProductCategoryId(), shopId);
assertEquals(1,count);
}
}
}
}
1.4 Junit用例指定执行顺序
在执行UT之前,有一点需要注意。就是执行Junit测试时,默认的顺序是随机的。在写UT的时候,有时需要按照顺序执行测试方法,已实现测试回环。
- MethodSorters.DEFAULT:以确定但不可预期的顺序去执行,默认。
- MethodSorters.JVM:按照JVM得到的方法顺序执行(不好控制),即代码中定义的方法顺序
- MethodSorters.NAME_ASCENDING:按照方法名字顺序去执行
package com.csj2018.o2o.dao;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.csj2018.o2o.BaseTest;
import com.csj2018.o2o.entity.ProductCategory;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ProductCategoryDaoTest extends BaseTest {
@Autowired
private ProductCategoryDao productCategoryDao;
@Test
// @Ignore
public void testBQueryByShopId() throws Exception {
long shopId = 1;
List<ProductCategory> productCategoryList = productCategoryDao.queryProductCategoryList(shopId);
System.out.println("该店铺自定义商品类别数为:"+productCategoryList.size());
}
@Test
// @Ignore
public void testABatchInsertProductCategory() {
ProductCategory productCategory1 = new ProductCategory();
productCategory1.setProductCategoryName("批量插入商品类别1");
productCategory1.setPriority(1);
productCategory1.setCreateTime(new Date());
productCategory1.setShopId(1L);
ProductCategory productCategory2 = new ProductCategory();
productCategory2.setProductCategoryName("批量插入商品类别2");
productCategory2.setPriority(2);
productCategory2.setCreateTime(new Date());
productCategory2.setShopId(1L);
List<ProductCategory> productCategoryList = new ArrayList<ProductCategory>();
productCategoryList.add(productCategory1);
productCategoryList.add(productCategory2);
int count = productCategoryDao.batchInsertProductCategory(productCategoryList);
assertEquals(2,count);
}
//7-5新增
@Test
public void testCDeleteProductCategory() {
long shopId = 1;
List<ProductCategory> productCategoryList = productCategoryDao.queryProductCategoryList(shopId);
for(ProductCategory pc:productCategoryList) {
if("批量插入商品类别1".equals(pc.getProductCategoryName())||"批量插入商品类别2".equals(pc.getProductCategoryName())) {
int count = productCategoryDao.deleteProductCategory(pc.getProductCategoryId(), shopId);
assertEquals(1,count);
}
}
}
}
![](https://img2020.cnblogs.com/blog/1418970/202003/1418970-20200308050226974-1670970958.png)
2 Service层
2.1 接口
package com.csj2018.o2o.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.csj2018.o2o.entity.ProductCategory;
public interface ProductCategoryDao {
/**
* 查询某个店铺下的商品分类
* @param shopId
* @return
*/
List<ProductCategory> queryProductCategoryList(long shopId);
/**
* 批量添加商品分类
* @param productCategoryList
* @return
*/
int batchInsertProductCategory(List<ProductCategory> productCategoryList);
/**
* 7-5删除商品类别
* @param productCategoryId
* @param shopId
* @return
*/
int deleteProductCategory(@Param("productCategoryId")long productCategoryId,@Param("shopId")long shopId);
}
2.2 实现类
package com.csj2018.o2o.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.csj2018.o2o.dao.ProductCategoryDao;
import com.csj2018.o2o.dto.ProductCategoryExecution;
import com.csj2018.o2o.entity.ProductCategory;
import com.csj2018.o2o.enums.ProductCategoryStateEnum;
import com.csj2018.o2o.exceptions.ProductCategoryOperationException;
import com.csj2018.o2o.service.ProductCategoryService;
@Service
public class ProductCategoryServiceImpl implements ProductCategoryService{
@Autowired
private ProductCategoryDao productCategoryDao;
@Override
public List<ProductCategory> getProductCategoryList(long shopId) {
// TODO Auto-generated method stub
return productCategoryDao.queryProductCategoryList(shopId);
}
//7.3增加
@Override
@Transactional
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);
}
}
//7-5
@Override
public ProductCategoryExecution deleteProductCategory(long productCategoryId, long shopId)
throws ProductCategoryOperationException {
// TODO 将该类别下的商品类别置为空,以后添加
try {
int effectedNum = productCategoryDao.deleteProductCategory(productCategoryId, shopId);
if(effectedNum <= 0) {
throw new ProductCategoryOperationException("商品类别删除失败");
}else {
return new ProductCategoryExecution(ProductCategoryStateEnum.SUCCESS);
}
}catch(Exception e) {
throw new ProductCategoryOperationException("delete ProductCategory error:"+e.getMessage());
}
}
}
3.controller层
package com.csj2018.o2o.web.shopadmin;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.csj2018.o2o.dto.ProductCategoryExecution;
import com.csj2018.o2o.dto.Result;
import com.csj2018.o2o.entity.ProductCategory;
import com.csj2018.o2o.entity.Shop;
import com.csj2018.o2o.enums.ProductCategoryStateEnum;
import com.csj2018.o2o.exceptions.ProductCategoryOperationException;
import com.csj2018.o2o.service.ProductCategoryService;
@Controller
@RequestMapping("/shopadmin")
public class ProductCategoryManagementController {
@Autowired
private ProductCategoryService productCategoryService;
@RequestMapping(value="/getproductcategorylist",method=RequestMethod.GET)
@ResponseBody
private Result<List<ProductCategory>> getProductCategoryList(HttpServletRequest request){
//测试用,可删除
// Shop shop = new Shop();
// shop.setShopId(1L);
// request.getSession().setAttribute("currentShop", shop);
Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
List<ProductCategory> list = null;
if(currentShop.getShopId() != null && currentShop.getShopId()>0){
list = productCategoryService.getProductCategoryList(currentShop.getShopId());
return new Result<List<ProductCategory>>(true,list);
}else {
ProductCategoryStateEnum ps = ProductCategoryStateEnum.INNER_ERROR;
return new Result<List<ProductCategory>>(false,ps.getState(),ps.getStateInfo());
}
}
@RequestMapping(value="/addproductcategory",method=RequestMethod.POST)
@ResponseBody
private Map<String,Object> addProductCategorys(@RequestBody List<ProductCategory> productCategoryList,HttpServletRequest request){
Map<String,Object> modelMap = new HashMap<String,Object>();
Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
for(ProductCategory pc:productCategoryList) {
pc.setShopId(currentShop.getShopId());
}
if(productCategoryList != null && productCategoryList.size()>0) {
try {
ProductCategoryExecution pe = productCategoryService.batchAddProductCategory(productCategoryList);
if(pe.getState() == ProductCategoryStateEnum.SUCCESS.getState()) {
modelMap.put("success", true);
}else {
modelMap.put("success", false);
modelMap.put("errMsg", pe.getStateInfo());
}
}catch (ProductCategoryOperationException e) {
modelMap.put("success", false);
modelMap.put("errMsg", e.toString());
}
}else {
modelMap.put("success", false);
modelMap.put("errMsg", "请输入至少一个商品类别");
}
return modelMap;
}
@RequestMapping(value="/removeproductcategory",method=RequestMethod.POST)
@ResponseBody
private Map<String,Object> removeProductCategory(Long productCategoryId,HttpServletRequest request){
Map<String,Object> modelMap = new HashMap<String,Object>();
if(productCategoryId != null && productCategoryId > 0) {
try {
Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
ProductCategoryExecution pe = productCategoryService.deleteProductCategory(productCategoryId, currentShop.getShopId());
if(pe.getState() == ProductCategoryStateEnum.SUCCESS.getState()) {
modelMap.put("success",true);
}else {
modelMap.put("success", false);
modelMap.put("errMsg", pe.getStateInfo());
}
}catch(ProductCategoryOperationException e) {
modelMap.put("success", false);
modelMap.put("errMsg", e.getMessage());
}
}else {
modelMap.put("success", false);
modelMap.put("errMsg", "请至少选择一个类别");
}
return modelMap;
}
}
4. 前端
只需要修改js即可
/**
*
*/
$(function(){
var listUrl = "/o2o/shopadmin/getproductcategorylist";
var addUrl = "/o2o/shopadmin/addproductcategory";
var deleteUrl = "/o2o/shopadmin/removeproductcategory";
getList();
function getList(){
$.getJSON(listUrl,function(data){
if(data.success){
var dataList = data.data;
$('.category-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>';
});
$('.category-wrap').append(tempHtml);
}
});
}
$('#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);
});
$('#submit').click(function(){
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:addUrl,
type:'POST',
data:JSON.stringify(productCategoryList),
contentType:'application/json',
success:function(data){
if(data.success){
$.toast("提交成功!");
getList();
}else{
$.toast("提交失败");
}
}
});
});
$('.category-wrap').on('click','.row-product-category.temp .delete',function(e){
console.log($(this).parent().parent());
$(this).parent().parent().remove();
});
$('.category-wrap').on('click','.row-product-category.now .delete',function(e){
var target = e.currentTarget;
$.confirm('确定删除吗?',function(){
$.ajax({
url:deleteUrl,
type:'POST',
data:{productCategoryId:target.dataset.id},
dataType:'json',
success:function(data){
if(data.success){
$.toast('删除成功!'),
getList();
}else{
$.toast('删除失败!');
}
}
});
});
});
})
验证,从前端删除原来的分类,删除成功,且列表自动更新
5.问题
5.1 js区分大小写
dataType:'json'中写为JSON,会不能正确解析json
5.2 dataset
html5中用data-前缀设置我们需要的自定义属性,来进行一些数据的存放。如
<div id="day-meal-expense" data-drink="tea" data-food="noodle" data-meal="lunch">$18.3</div>
而dataset会将所有的data-前缀的属性组合为一个键值对。
var expenseday = document.getElementById('day-meal-expense');
console.log(expenseday.dataset); //{ "drink" : "tea" , "food" : "noodle" , "meal" : "lunch" }
参考:https://blog.csdn.net/qq_39579242/article/details/81779170