实战SSM_O2O商铺_27【商品类别】删除商品类别从Dao到View层的开发_实战SSM

概述

上篇博客 实战SSM_O2O商铺_26【商品类别】批量新增商品类别从Dao到View层的开发实现了商品目录的批量添加功能,我们按照既定的设计,继续来完成商品目录的修改吧。


Dao层

ProductCategoryDao接口增加接口方法

/**
	 * 
	 * 
	 * @Title: deleteProductCategory
	 * 
	 * @Description: 删除特定shop下的productCategory
	 * 
	 * @param productCategoryId
	 * @param shopId
	 * 
	 * @return: int
	 */
	int deleteProductCategory(@Param("productCategoryId") Long productCategoryId, @Param("shopId") Long shopId);

ProductCategoryDao SQL映射文件


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

闭环的单元测试

这里我们使用Junit 4.11里及其以后的版本中增加的@FixMethodOrder注解来实现. 具体见代码注释。

package com.artisan.o2o.dao;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;

import com.artisan.o2o.BaseTest;
import com.artisan.o2o.entity.ProductCategory;

/**
 * 
 * 
 * @ClassName: ProductCategoryTest
 * 
 * @Description: Junit 4.11里增加了指定测试方法执行顺序的特性 .
 * 
 *               测试类的执行顺序可通过对测试类添加注解@FixMethodOrder(value) 来指定,其中value 为执行顺序
 * 
 *               三种执行顺序可供选择:
 * 
 *               默认(MethodSorters.DEFAULT),
 *               默认顺序由方法名hashcode值来决定,如果hash值大小一致,则按名字的字典顺序确定
 *               由于hashcode的生成和操作系统相关
 *               (以native修饰),所以对于不同操作系统,可能会出现不一样的执行顺序,在某一操作系统上,多次执行的顺序不变
 * 
 *               按方法名( MethodSorters.NAME_ASCENDING)【推荐】,
 *               按方法名称的进行排序,由于是按字符的字典顺序,所以以这种方式指定执行顺序会始终保持一致;
 *               不过这种方式需要对测试方法有一定的命名规则,如 测试方法均以testNNN开头(NNN表示测试方法序列号 001-999)
 * 
 *               JVM(MethodSorters.JVM)
 *               按JVM返回的方法名的顺序执行,此种方式下测试方法的执行顺序是不可预测的,即每次运行的顺序可能都不一样
 * 
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年6月21日 下午11:55:45
 */
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ProductCategoryTest extends BaseTest {
	
	@Autowired
	ProductCategoryDao productCategoryDao;
	
	@Test
	public void testB_SelectProductCategoryList() {
		long shopId = 5L;
		List<ProductCategory> productCategories = productCategoryDao.selectProductCategoryList(shopId);
		// shopId = 5 有2条测试数据,期望list中有2条
		assertEquals(2, productCategories.size());
		// SQL中按照权重排序, product1 priority 99 ,期望第一条数据是 product1
		assertEquals("product1", productCategories.get(0).getProductCategoryName());

		for (ProductCategory productCategory : productCategories) {
			System.out.println(productCategory.toString());
		}

		productCategories = productCategoryDao.selectProductCategoryList(6L);
		assertEquals(0, productCategories.size());

	}

	@Test
	public void testA_BatchInsertProductCategory() {

		ProductCategory productCategory1 = new ProductCategory();
		productCategory1.setProductCategoryName("product1");
		productCategory1.setProductCategoryDesc("product1_desc");
		productCategory1.setPriority(99);
		productCategory1.setCreateTime(new Date());
		productCategory1.setLastEditTime(new Date());
		productCategory1.setShopId(5L);

		ProductCategory productCategory2 = new ProductCategory();
		productCategory2.setProductCategoryName("product2");
		productCategory2.setProductCategoryDesc("product2_desc");
		productCategory2.setPriority(98);
		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);

	}

	@Test
	public void testC_DeleteProductCategory() {
		// 查询出来shopId=5的商铺下面全部的商品目录
		List<ProductCategory> productCategoryList = productCategoryDao.selectProductCategoryList(5L);
		// 遍历循环删除
		for (ProductCategory productCategory : productCategoryList) {
			if ("product1".equals(productCategory.getProductCategoryName()) || "product2".equals(productCategory.getProductCategoryName())) {
				int effectNum = productCategoryDao.deleteProductCategory(productCategory.getProductCategoryId(), 5L);
				assertEquals(1, effectNum);
			}
		}
	}

}

运行单元测试

实战SSM_O2O商铺_27【商品类别】删除商品类别从Dao到View层的开发_SSM教程_02

日志信息:

JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@7fb95505] will not be managed by Spring
==>  Preparing: INSERT INTO tb_product_category( product_category_name, product_category_desc, priority, create_time, last_edit_time, shop_id) VALUES ( ?, ?, ?, ?, ?, ? ) , ( ?, ?, ?, ?, ?, ? ) 
==> Parameters: product1(String), product1_desc(String), 99(Integer), 2018-06-22 00:17:25.611(Timestamp), 2018-06-22 00:17:25.611(Timestamp), 5(Long), product2(String), product2_desc(String), 98(Integer), 2018-06-22 00:17:25.612(Timestamp), 2018-06-22 00:17:25.612(Timestamp), 5(Long)
<==    Updates: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@38b27cdc]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@336f1079] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@21fd5faa] will not be managed by Spring
==>  Preparing: SELECT tpc.product_category_id, tpc.product_category_name, tpc.product_category_desc, tpc.priority, tpc.create_time, tpc.last_edit_time, tpc.shop_id FROM tb_product_category tpc WHERE tpc.shop_id = ? ORDER BY priority DESC 
==> Parameters: 5(Long)
<==    Columns: product_category_id, product_category_name, product_category_desc, priority, create_time, last_edit_time, shop_id
<==        Row: 24, product1, product1_desc, 99, 2018-06-22 00:17:26.0, 2018-06-22 00:17:26.0, 5
<==        Row: 25, product2, product2_desc, 98, 2018-06-22 00:17:26.0, 2018-06-22 00:17:26.0, 5
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@336f1079]
ProductCategory [productCategoryId=24, shopId=5, productCategoryName=product1, productCategoryDesc=product1_desc, priority=99, createTime=Fri Jun 22 00:17:26 BOT 2018, lastEditTime=Fri Jun 22 00:17:26 BOT 2018]
ProductCategory [productCategoryId=25, shopId=5, productCategoryName=product2, productCategoryDesc=product2_desc, priority=98, createTime=Fri Jun 22 00:17:26 BOT 2018, lastEditTime=Fri Jun 22 00:17:26 BOT 2018]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@19b93fa8] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@1f010bf0] will not be managed by Spring
==>  Preparing: SELECT tpc.product_category_id, tpc.product_category_name, tpc.product_category_desc, tpc.priority, tpc.create_time, tpc.last_edit_time, tpc.shop_id FROM tb_product_category tpc WHERE tpc.shop_id = ? ORDER BY priority DESC 
==> Parameters: 6(Long)
<==      Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@19b93fa8]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7f132176] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@2631f68c] will not be managed by Spring
==>  Preparing: SELECT tpc.product_category_id, tpc.product_category_name, tpc.product_category_desc, tpc.priority, tpc.create_time, tpc.last_edit_time, tpc.shop_id FROM tb_product_category tpc WHERE tpc.shop_id = ? ORDER BY priority DESC 
==> Parameters: 5(Long)
<==    Columns: product_category_id, product_category_name, product_category_desc, priority, create_time, last_edit_time, shop_id
<==        Row: 24, product1, product1_desc, 99, 2018-06-22 00:17:26.0, 2018-06-22 00:17:26.0, 5
<==        Row: 25, product2, product2_desc, 98, 2018-06-22 00:17:26.0, 2018-06-22 00:17:26.0, 5
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7f132176]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5443d039] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@7d1cfb8b] will not be managed by Spring
==>  Preparing: DELETE FROM tb_product_category WHERE product_category_id = ? and shop_id = ? 
==> Parameters: 24(Long), 5(Long)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5443d039]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6e4566f1] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@344f4dea] will not be managed by Spring
==>  Preparing: DELETE FROM tb_product_category WHERE product_category_id = ? and shop_id = ? 
==> Parameters: 25(Long), 5(Long)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6e4566f1]


Servie层

接口

/**
	 * 
	 * 
	 * @Title: deleteProductCategory
	 * 
	 * @Description: TODO 需要先将该商品目录下的商品的类别Id置为空,然后再删除该商品目录, 因此需要事务控制
	 * 
	 * @param productCategoryId
	 * @param shopId
	 * @throws ProductCategoryOperationException
	 * 
	 * @return: ProductCategoryExecution
	 */
	ProductCategoryExecution deleteProductCategory(long productCategoryId, long shopId) throws ProductCategoryOperationException;

接口实现

/**
	 * TODO 需要先将该商品目录下的商品的类别Id置为空,然后再删除该商品目录, 因此需要事务控制@Transactional
	 */
	@Override
	@Transactional
	public ProductCategoryExecution deleteProductCategory(long productCategoryId, long shopId) throws ProductCategoryOperationException {
		// TODO 第一步 需要先将该商品目录下的商品的类别Id置为空

		// 第二步 删除该商品目录
		try {
			int effectNum = productCategoryDao.deleteProductCategory(productCategoryId, shopId);
			if (effectNum > 0) {
				return new ProductCategoryExecution(ProductCategoryStateEnum.SUCCESS);
			} else {
				return new ProductCategoryExecution(ProductCategoryStateEnum.INNER_ERROR);
			}
		} catch (Exception e) {
			throw new ProductCategoryOperationException(e.getMessage());
		}
	}

单元测试

@Test
	public void testDeleteProductCategory() {

		ProductCategoryExecution productCategoryExecution = productCategoryService.deleteProductCategory(26, 5);
		Assert.assertEquals(1, productCategoryExecution.getState());
		ProductCategoryExecution productCategoryExecution2 = productCategoryService.deleteProductCategory(27, 5);
		Assert.assertEquals(1, productCategoryExecution2.getState());
	}

Controller层

路由方法

/**
	 * 
	 * 
	 * @Title: remooveProductCategory
	 * 
	 * @Description: 删除商品目录
	 * 
	 * @param productCategoryId
	 * @param request
	 * 
	 * @return: Map<String,Object>
	 */
	@RequestMapping(value = "/removeproductcategory", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> remooveProductCategory(Long productCategoryId, HttpServletRequest request) {
		Map<String, Object> modelMap = new HashMap<String, Object>();
		if (productCategoryId != null && productCategoryId > 0) {
			// 从session中获取shop的信息
			Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
			if (currentShop != null && currentShop.getShopId() != null) {
				try {
					// 删除
					Long shopId = currentShop.getShopId();
					ProductCategoryExecution pce = productCategoryService.deleteProductCategory(productCategoryId, shopId);
					if (pce.getState() == ProductCategoryStateEnum.SUCCESS.getState()) {
						modelMap.put("success", true);
					} 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

增加如下代码

 var deleteProductCategoryUrl = '/o2o/shopadmin/removeproductcategory';

// 一种是需要提交到后台的删除  now  ,另外一种是 新增但未提交到数据库中的删除 temp
	
	$('.product-categroy-wrap').on('click', '.row-product-category.now .delete',
			function(e) {
				var target = e.currentTarget;
				$.confirm('确定么?', function() {
					$.ajax({
						url : deleteProductCategoryUrl,
						type : 'POST',
						data : {
							productCategoryId : target.dataset.id,
						},
						dataType : 'json',
						success : function(data) {
							if (data.success) {
								$.toast('删除成功!');
								// 重新加载数据
								getProductCategoryList();
							} else {
								$.toast('删除失败!');
							}
						}
					});
				});
			});

	$('.product-categroy-wrap').on('click', '.row-product-category.temp .delete',
			function(e) {
				$(this).parent().parent().remove();
			});


联调

前端页面debug, 后端也可以加入断点,以debug的方式开启tomcat,逐步调测

效果如下:

实战SSM_O2O商铺_27【商品类别】删除商品类别从Dao到View层的开发_实战SSM_03


Github地址

代码地址: https://github.com/yangshangwei/o2o