实战SSM_O2O商铺_36【商品】商品列表之Dao+Service+Controller层的实现

概述

接着继续来完成商品列表的功能吧,需要支持分页的功能。


Dao层

ProductDao.java

增加如下两个接口

/**
	 * 
	 * 
	 * @Title: selectProductList
	 * 
	 * @Description: 支持分页功能的查询product
	 * 
	 *               需要支持根据商品名称(支持模糊查询)、商品状态、shopId、商品类别的查询及组合查询
	 * 
	 * @param productCondition
	 * @param rowIndex
	 *            从第几行开始取
	 * @param pageSize
	 *            返回多少行数据(页面上的数据量)
	 * 
	 *            比如 rowIndex为1,pageSize为5 即为 从第一行开始取,取5行数据
	 * 
	 * @return: List<Product>
	 */
	List<Product> selectProductList(@Param("productCondition") Product productCondition, @Param("rowIndex") int rowIndex, @Param("pageSize") int pageSize);

	/**
	 * 
	 * 
	 * @Title: selectCountProduct
	 * 
	 * @Description: 按照条件查询 符合前台传入的条件的商品的总数
	 * 
	 * @param productCondition
	 * @return
	 * 
	 * @return: int
	 */
	int selectCountProduct(@Param("productCondition") Product productCondition);


ProductDao.xml

增加如下SQL映射

<sql id="selectProductByCondition">
		<!-- 根据shopId 查询-->
		<if test="productCondition.shop != null and  productCondition.shop.shopId != null ">
			and shop_id = #{productCondition.shop.shopId}
		</if>
		<!-- 根据product_category_id  查询-->
		<if test="productCondition.productCategory != null and productCondition.productCategory.productCategoryId != null">
			and product_category_id = #{productCondition.productCategory.productCategoryId}
		</if>
		<!-- 根据enable_status  查询-->
		<if test="productCondition.enableStatus != null">
			and enable_status = #{productCondition.enableStatus}
		</if>
		<!-- 根据product_name  模糊查询-->
		<if test="productCondition.productName != null">
			and product_name  like '%${productCondition.productName}%'
		</if>
</sql>


<select id="selectProductList" resultType="com.artisan.o2o.entity.Product">
		SELECT
			product_id,
			product_name,
			product_desc,
			img_addr,
			normal_price,
			promotion_price,
			priority,
			create_time,
			last_edit_time,
			enable_status,
			product_category_id,
			shop_id
		FROM
			tb_product	
		<where>
			<include refid="selectProductByCondition"></include>
		</where>
		ORDER BY 
			priority desc 
		LIMIT  #{rowIndex} ,#{pageSize}
	</select>
	
	
	<select id="selectCountProduct" resultType="Integer">
		SELECT
			count(1)
		FROM
			tb_product
		<where>
			<include refid="selectProductByCondition"></include>
		</where>
	</select>

单元测试

	@Test
	public void testC_SelectProductListAndCount() {
		int rowIndex = 1;
		int pageSize = 2;
		List<Product> productList = new ArrayList<Product>();
		int effectNum = 0;

		Shop shop = new Shop();
		shop.setShopId(5L);

		Product productCondition = new Product();
		productCondition.setShop(shop);

		productList = productDao.selectProductList(productCondition, rowIndex, pageSize);
		Assert.assertEquals(2, productList.size());

		effectNum = productDao.selectCountProduct(productCondition);
		Assert.assertEquals(7, effectNum);

		System.out.println("==========================================");

		Shop shop2 = new Shop();
		shop2.setShopId(5L);


		ProductCategory productCategory = new ProductCategory();
		productCategory.setProductCategoryId(36L);

		Product productCondition2 = new Product();
		productCondition2.setShop(shop2);
		productCondition2.setProductCategory(productCategory);
		productCondition2.setProductName("test");

		productList = productDao.selectProductList(productCondition2, rowIndex, pageSize);
		Assert.assertEquals(2, productList.size());

		effectNum = productDao.selectCountProduct(productCondition2);
		Assert.assertEquals(5, effectNum);
	}

结合tb_product中的记录,验证是否符合预期,这里单元测试通过。

这里写图片描述

JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@29a0cdb] will not be managed by Spring
==>  Preparing: SELECT product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id FROM tb_product WHERE shop_id = ? ORDER BY priority desc LIMIT ? ,? 
==> Parameters: 5(Long), 1(Integer), 2(Integer)
<==    Columns: product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id
<==        Row: 2, modifyProduct, modifyProduct desc, /mmm/ddd, 350, 300, 66, 2018-06-29 17:46:46.0, 2018-06-30 16:02:01.0, 1, 36, 5
<==        Row: 3, test_product, product desc, /aaa/bbb, 10, 8, 66, 2018-06-24 18:45:36.0, 2018-06-24 18:45:36.0, 1, 36, 5
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@492691d7]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b94089b] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@47f9738] will not be managed by Spring
==>  Preparing: SELECT count(1) FROM tb_product WHERE shop_id = ? 
==> Parameters: 5(Long)
<==    Columns: count(1)
<==        Row: 7
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b94089b]
==========================================
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@388526fb] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6436a7db] will not be managed by Spring
==>  Preparing: SELECT product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id FROM tb_product WHERE shop_id = ? and product_category_id = ? and product_name like '%test%' ORDER BY priority desc LIMIT ? ,? 
==> Parameters: 5(Long), 36(Long), 1(Integer), 2(Integer)
<==    Columns: product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id
<==        Row: 4, test_product, product desc, \upload\item\shopImage\5\2018062515593428322.jpg, 10, 8, 66, 2018-06-25 15:58:16.0, 2018-06-25 15:58:17.0, 1, 36, 5
<==        Row: 5, test_product, product desc, \upload\item\shopImage\5\2018062516124013361.jpg, 10, 8, 66, 2018-06-25 16:12:40.0, 2018-06-25 16:12:40.0, 1, 36, 5
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@388526fb]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40238dd0] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@79179359] will not be managed by Spring
==>  Preparing: SELECT count(1) FROM tb_product WHERE shop_id = ? and product_category_id = ? and product_name like '%test%' 
==> Parameters: 5(Long), 36(Long)
<==    Columns: count(1)
<==        Row: 5
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40238dd0]

Service层

Service接口层只需要提供一个方法即可,内部调用Dao层的两个方法,将返回结果封装到DTO中。

ProductService.java

	/**
	 * 
	 * 
	 * @Title: queryProductionList
	 * 
	 * @Description: 查询
	 * 
	 * @param productCondition
	 * @param pageIndex
	 *            前端页面 只有第几页 第几页 定义为pageIndex
	 * @param pageSize
	 *            一页中展示的行数
	 * @throws ProductOperationException
	 * 
	 * @return: ProductExecution
	 */
	ProductExecution queryProductionList(Product productCondition, int pageIndex, int pageSize) throws ProductOperationException;


ProductServiceImpl.java

@Override
	public ProductExecution queryProductionList(Product productCondition, int pageIndex, int pageSize) throws ProductOperationException {
		List<Product> productList = null;
		int count = 0;
		try {
			// 将pageIndex 转换为Dao层识别的rowIndex
			int rowIndex = PageCalculator.calculateRowIndex(pageIndex, pageSize);
			// 调用Dao层获取productList和总量
			productList = productDao.selectProductList(productCondition, rowIndex, pageSize);
			count = productDao.selectCountProduct(productCondition);
		} catch (Exception e) {
			e.printStackTrace();
			new ProductExecution(ProductStateEnum.INNER_ERROR);
		}
		return new ProductExecution(ProductStateEnum.SUCCESS, productList, count);
	}

单元测试

@Test
	public void testQueryProductListAndCount() {
		// 库表中符合如下筛选条件的记录为5条
		// select * from tb_product a where a.product_category_id = 36 and
		// a.shop_id = 5 and a.product_name like '%test%';

		// 从第1页开始取,每页取3条
		int pageIndex = 1;
		int pageSize = 3;

		Shop shop2 = new Shop();
		shop2.setShopId(5L);

		ProductCategory productCategory = new ProductCategory();
		productCategory.setProductCategoryId(36L);

		Product productCondition = new Product();
		productCondition.setShop(shop2);
		productCondition.setProductCategory(productCategory);
		productCondition.setProductName("test");


		ProductExecution productExecution = productService.queryProductionList(productCondition, pageIndex, pageSize);
		// 操作成功的状态为1
		Assert.assertEquals(1, productExecution.getState());
		Assert.assertEquals(3, productExecution.getProductList().size());
		Assert.assertEquals(5, productExecution.getCount());

		// 从第2页开始取,每页依然取3条
		pageIndex = 2;
		productExecution = productService.queryProductionList(productCondition, pageIndex, pageSize);
		Assert.assertEquals(1, productExecution.getState());
		Assert.assertEquals(2, productExecution.getProductList().size());
		Assert.assertEquals(5, productExecution.getCount());

	}

这里写图片描述

JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@177bea38] will not be managed by Spring
==>  Preparing: SELECT product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id FROM tb_product WHERE shop_id = ? and product_category_id = ? and product_name like '%test%' ORDER BY priority desc LIMIT ? ,? 
==> Parameters: 5(Long), 36(Long), 0(Integer), 3(Integer)
<==    Columns: product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id
<==        Row: 3, test_product, product desc, /aaa/bbb, 10, 8, 66, 2018-06-24 18:45:36.0, 2018-06-24 18:45:36.0, 1, 36, 5
<==        Row: 4, test_product, product desc, \upload\item\shopImage\5\2018062515593428322.jpg, 10, 8, 66, 2018-06-25 15:58:16.0, 2018-06-25 15:58:17.0, 1, 36, 5
<==        Row: 5, test_product, product desc, \upload\item\shopImage\5\2018062516124013361.jpg, 10, 8, 66, 2018-06-25 16:12:40.0, 2018-06-25 16:12:40.0, 1, 36, 5
<==      Total: 3
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4716be8b]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@460ebd80] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@74f5ce22] will not be managed by Spring
==>  Preparing: SELECT count(1) FROM tb_product WHERE shop_id = ? and product_category_id = ? and product_name like '%test%' 
==> Parameters: 5(Long), 36(Long)
<==    Columns: count(1)
<==        Row: 5
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@460ebd80]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@dbd8e44] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6a55299e] will not be managed by Spring
==>  Preparing: SELECT product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id FROM tb_product WHERE shop_id = ? and product_category_id = ? and product_name like '%test%' ORDER BY priority desc LIMIT ? ,? 
==> Parameters: 5(Long), 36(Long), 3(Integer), 3(Integer)
<==    Columns: product_id, product_name, product_desc, img_addr, normal_price, promotion_price, priority, create_time, last_edit_time, enable_status, product_category_id, shop_id
<==        Row: 6, test_product, product desc, \upload\item\shopImage\5\2018062516132272045.jpg, 10, 8, 66, 2018-06-25 16:13:22.0, 2018-06-25 16:13:22.0, 1, 36, 5
<==        Row: 8, test_product, product desc, /aaa/bbb, 10, 8, 66, 2018-06-30 16:01:59.0, 2018-06-30 16:01:59.0, 1, 36, 5
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@dbd8e44]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5a18cd76] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@403f0a22] will not be managed by Spring
==>  Preparing: SELECT count(1) FROM tb_product WHERE shop_id = ? and product_category_id = ? and product_name like '%test%' 
==> Parameters: 5(Long), 36(Long)
<==    Columns: count(1)
<==        Row: 5
<==      Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5a18cd76]


Controller层

ProductController.java

增加如下路由方法

	@RequestMapping(value = "/getproductlist", method = RequestMethod.GET)
	@ResponseBody
	private Map<String, Object> queryProductList(HttpServletRequest request) {
		Map<String, Object> modelMap = new HashMap<String, Object>();
		// 获取前端传递过来的页码
		int pageIndex = HttpServletRequestUtil.getInt(request, "pageIndex");
		// 获取前端传过来的每页要求返回的商品数量
		int pageSize = HttpServletRequestUtil.getInt(request, "pageSize");

		// 从session中获取shop信息,主要是获取shopId 不依赖前台的参数,尽可能保证安全
		Shop currentShop = (Shop) request.getSession().getAttribute("currentShop");
		// 空值判断
		if ((pageIndex > -1) && (pageSize > -1) && currentShop != null && currentShop.getShopId() != null) {
			// 获取前台可能传递过来的需要检索的条件,包括是否需要从某个商品类别以及根据商品名称模糊查询某个店铺下的商品
			long productCategoryId = HttpServletRequestUtil.getLong(request, "productCategoryId");
			String productName = HttpServletRequestUtil.getString(request, "productName");
			// 拼装查询条件,根据前端传入的条件进行组合
			Product productCondition = compactProductCondition4Search(currentShop.getShopId(), productCategoryId, productName);
			// 调用服务
			ProductExecution pe = productService.queryProductionList(productCondition, pageIndex, pageSize);
			// 将结果返回给前台
			modelMap.put("productList", pe.getProductList());
			modelMap.put("count", pe.getCount());
			modelMap.put("success", true);
		} else {
			modelMap.put("success", false);
			modelMap.put("errMsg", "empty pageSize or pageIndex or shopId");
		}
		return modelMap;
	}

	/**
	 * 
	 * 
	 * @Title: compactProductCondition4Search
	 * 
	 * @Description: 组装查询条件
	 * 
	 * @param shopId
	 * @param productCategoryId
	 * @param productName
	 * 
	 * @return: Product
	 */
	private Product compactProductCondition4Search(Long shopId, long productCategoryId, String productName) {
		Product productCondition = new Product();
		Shop shop = new Shop();
		shop.setShopId(shopId);
		productCondition.setShop(shop);
		if (productCategoryId != -1L) {
			ProductCategory productCategory = new ProductCategory();
			productCategory.setProductCategoryId(productCategoryId);
			productCondition.setProductCategory(productCategory);
		}
		if (productName != null) {
			productCondition.setProductName(productName);
		}
		return productCondition;
	}

单元测试

启动tomcat的服务,第一次可以加入断点,使用debug的方式启动逐步调测该方法。

先获取shoplist,然后进入shop管理页面,使后端将该shop的信息写入到session中。 因为这个方法的shop信息是从session中获取的。

最后访问

http://localhost:8080/o2o/shopadmin/getproductlist?pageIndex=1&&pageSize=8

根据数据库中的记录,合理设置pageIndex和pageSize,多次验证获取的数据是否符合预期。

{
    "success": true,
    "count": 7,
    "productList": [
        {
            "productId": 7,
            "productName": "offical_product1",
            "productDesc": "product offical desc1",
            "imgAddr": "\\upload\\item\\shopImage\\5\\2018070123313434331.png",
            "normalPrice": "1001",
            "promotionPrice": "801",
            "priority": 661,
            "createTime": 1530286468000,
            "lastEditTime": 1530502295000,
            "enableStatus": 1,
            "productImgList": null,
            "productCategory": null,
            "shop": null
        },
        {
            "productId": 2,
            "productName": "modifyProduct",
            "productDesc": "modifyProduct desc",
            "imgAddr": "/mmm/ddd",
            "normalPrice": "350",
            "promotionPrice": "300",
            "priority": 66,
            "createTime": 1530308806000,
            "lastEditTime": 1530388921000,
            "enableStatus": 1,
            "productImgList": null,
            "productCategory": null,
            "shop": null
        },
        {
            "productId": 3,
            "productName": "test_product",
            "productDesc": "product desc",
            "imgAddr": "/aaa/bbb",
            "normalPrice": "10",
            "promotionPrice": "8",
            "priority": 66,
            "createTime": 1529880336000,
            "lastEditTime": 1529880336000,
            "enableStatus": 1,
            "productImgList": null,
            "productCategory": null,
            "shop": null
        },
        {
            "productId": 4,
            "productName": "test_product",
            "productDesc": "product desc",
            "imgAddr": "\\upload\\item\\shopImage\\5\\2018062515593428322.jpg",
            "normalPrice": "10",
            "promotionPrice": "8",
            "priority": 66,
            "createTime": 1529956696000,
            "lastEditTime": 1529956697000,
            "enableStatus": 1,
            "productImgList": null,
            "productCategory": null,
            "shop": null
        },
        {
            "productId": 5,
            "productName": "test_product",
            "productDesc": "product desc",
            "imgAddr": "\\upload\\item\\shopImage\\5\\2018062516124013361.jpg",
            "normalPrice": "10",
            "promotionPrice": "8",
            "priority": 66,
            "createTime": 1529957560000,
            "lastEditTime": 1529957560000,
            "enableStatus": 1,
            "productImgList": null,
            "productCategory": null,
            "shop": null
        },
        {
            "productId": 6,
            "productName": "test_product",
            "productDesc": "product desc",
            "imgAddr": "\\upload\\item\\shopImage\\5\\2018062516132272045.jpg",
            "normalPrice": "10",
            "promotionPrice": "8",
            "priority": 66,
            "createTime": 1529957602000,
            "lastEditTime": 1529957602000,
            "enableStatus": 1,
            "productImgList": null,
            "productCategory": null,
            "shop": null
        },
        {
            "productId": 8,
            "productName": "test_product",
            "productDesc": "product desc",
            "imgAddr": "/aaa/bbb",
            "normalPrice": "10",
            "promotionPrice": "8",
            "priority": 66,
            "createTime": 1530388919000,
            "lastEditTime": 1530388919000,
            "enableStatus": 1,
            "productImgList": null,
            "productCategory": null,
            "shop": null
        }
    ]
}

Github地址

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

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SSM(Spring + Spring MVC + MyBatis)框架中,ControllerServiceDAO的执行过程如下: 1. Controller接收请求:当用户发送一个请求时,请求首先通过DispatcherServlet(前端控制器)进入Spring MVC框架。DispatcherServlet根据请求的URL和配置的路径映射,将请求发给相应的Controller类。 2. Controller处理请求:Controller类中的方法使用注解(如@RequestMapping)来映射特定的URL,并处理请求。在Controller方法中,可以通过参数注解(如@PathVariable、@RequestParam)获取请求参数,并调用Service的方法来处理业务逻辑。 3. Service处理业务逻辑:Service是应用程序的业务逻辑,它接收Controller传递的请求,并通过调用DAO提供的方法来访问数据库。在Service,可以进行事务管理、数据换、复杂的业务计算等任务。 4. DAO访问数据库:DAO负责与数据库交互,封装了对数据库的增删改查等基本操作。DAO通过MyBatis框架提供的ORM(对象关系映射)功能,将数据库表映射为Java对象,通过SQL语句执行数据库操作。 5. 数据库操作完成后,数据返回给ServiceDAO执行完数据库操作后,将查询结果或操作结果返回给Service。 6. Service将结果返回给ControllerService接收到DAO返回的结果后,可以对结果进行处理、封装,然后将结果返回给Controller。 7. Controller返回响应:Controller接收到Service返回的结果后,可以进行一些额外的处理(如数据换、视图解析等),然后将结果返回给前端,生成响应。 总结来说,Controller负责接收请求和返回响应,Service负责处理业务逻辑,DAO负责与数据库交互。它们之间通过调用方法和传递数据来完成整个请求处理流程。这样的分架构可以提高代码的可维护性、可测试性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值