实战SSM_O2O商铺_32【商品】商品编辑之Dao层的实现

2021-08-17 14:32:04 浏览数 (1)

文章目录

  • 概述
  • Dao层接口
    • ProductDao#selectProductById
    • ProductDao#updateProduct
    • ProductImgDao#deleteProductImgById
    • ProductImgDao#selectProductImgList
  • Mapper映射文件
    • ProductDao.xml
    • ProductImgDao.xml
  • 单元测试
    • ProductDaoTest
    • ProductImgDaoTest
  • Github地址

概述

完成了商品的添加Dao层到View层功能之后,

实战SSM_O2O商铺_28【商品】商品添加之Dao层的实现

实战SSM_O2O商铺_29【商品】商品添加之Service层的实现及重构

实战SSM_O2O商铺_30【商品】商品添加之Controller层的实现

实战SSM_O2O商铺_31【商品】商品添加之View层的实现

我们先来看下商品的编辑,最后做商品列表展示,当然了,可根据个人习惯,调整开发顺序。


说到商品编辑,

  • 首先肯定要根据productId查到对应Product相关的信息,既然这里是Dao层的开发,所以需要在Dao层需要开发一个 selectProductById 方法
  • 商品信息有商品缩略图和详情图片,这里我们先约定好:如果用户传入了新的商品缩略图和详情图片,就将原有的商品缩略图和详情图片删除掉。

  • 商品缩略图的地址存放在tb_product的img_addr字段,所以只需要更新改表即可。 所以对应Dao层应该有个方法updateProduct
  • 图片缩略图还涉及磁盘上的文件的删除,需要根据productId获取到Product ,然后获取Product的imgAddr属性,复用selectProductById 解渴
  • 详情图片的地址存放在tb_product_img中,根据product_id可以查找到对应商品下的全部详情图片,所以对应Dao层应该有个方法deleteProductImgById
  • 图片详情还涉及磁盘上的文件的删除,需要根据productId获取到List ,然后遍历该list,获取集合中每个ProductImg的imgAddr地址,所以还需要有个selectProductImgList方法

Dao层接口

ProductDao#selectProductById

代码语言:javascript复制
/**
	 * 
	 * 
	 * @Title: selectProductById
	 * 
	 * @Description: 根据productId查询product
	 * 
	 * @param productId
	 * 
	 * @return: Product
	 */
	Product selectProductById(long productId);

ProductDao#updateProduct

代码语言:javascript复制
/**
	 * 
	 * 
	 * @Title: updateProduct
	 * 
	 * @Description: 修改商品
	 * 
	 * @param product
	 * 
	 * @return: int
	 */
	int updateProduct(Product product);

ProductImgDao#deleteProductImgById

代码语言:javascript复制
/**
	 * 
	 * 
	 * @Title: deleteProductImgById
	 * 
	 * @Description: 删除商品对应的商品详情图片
	 * 
	 * @param productId
	 * 
	 * @return: int
	 */
	int deleteProductImgById(long productId);

ProductImgDao#selectProductImgList

代码语言:javascript复制
	/**
	 * 
	 * 
	 * @Title: selectProductImgList
	 * 
	 * @Description: 根据productId查询商铺对应的图片详情信息
	 * 
	 * @param productId
	 * 
	 * @return: List
	 */
	List selectProductImgList(long productId);

Mapper映射文件

ProductDao.xml

说明见注释

代码语言:javascript复制
<?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.artisan.o2o.dao.ProductDao">
	
	<resultMap id="productMap" type="com.artisan.o2o.entity.Product" >
		<id column="product_id" property="productId"/>
		<!-- property对应实体类中的属性名  column 对应库表中的字段名 -->
		<result column="product_name" property="productName"/>
		<result column="product_desc" property="productDesc"/>
		<result column="img_addr" property="imgAddr" />
		<result column="normal_price" property="normalPrice" />
		<result column="promotion_price" property="promotionPrice" />
		<result column="priority" property="priority" />
		<result column="create_time" property="createTime" />
		<result column="last_edit_time" property="lastEditTime" />
		<result column="enable_status" property="enableStatus" />
		
		<!-- 一对一使用association  
			product中的属性为productCategory, 通过数据库中的product_category_id关联起来的
			类型为 com.artisan.o2o.entity.ProductCategory-->
		<association property="productCategory" column="product_category_id"
			javaType="com.artisan.o2o.entity.ProductCategory">
			<!-- 对应ProductCategory中的属性 和 tb_product_category的字段 -->
			<id column="product_category_id" property="productCategoryId" />
			<result column="product_category_name" property="productCategoryName" />
		</association>
		
		<!-- 一对一使用association  
			product中的属性为shop, 通过数据库中的shop_id关联起来的
			类型为com.artisan.o2o.entity.Shop-->
		<association property="shop" column="shop_id"
			javaType="com.artisan.o2o.entity.Shop">
			<id column="shop_id" property="shopId" />
			<!-- 对应Shop中的属性 和 tb_shop的字段 ,如果是符合对象,使用xx.xxx的方式-->
			<result column="owner_id" property="owner.userId" />
			<result column="shop_name" property="shopName" />
		</association>
		<!-- 一对多使用collection  
			product中的属性为productImgList,并且是通过库表中的product_id关联起来的,
			保存的类型为com.imooc.myo2o.entity.ProductImg -->
		<collection property="productImgList" column="product_id"
			ofType="com.artisan.o2o.entity.ProductImg">
			<id column="product_img_id" property="productImgId" />
			<result column="img_addr" property="imgAddr" />
			<result column="img_desc" property="imgDesc" />
			<result column="priority" property="priority" />
			<result column="create_time" property="createTime" />
			<result column="product_id" property="productId" />
		</collection>
		
		
	</resultMap>
	
	<insert id="insertProduct" 
		parameterType="com.artisan.o2o.entity.Product" 
		useGeneratedKeys="true" keyProperty="productId" keyColumn="product_id">
		INSERT INTO
			tb_product
			(
				product_name,
				product_desc,
				img_addr,
				normal_price,
				promotion_price,
				priority,
				create_time,
				last_edit_time,
				enable_status,
				product_category_id,
				shop_id
			)
		VALUES(
			#{productName},
			#{productDesc},
			#{imgAddr},
			#{normalPrice},
			#{promotionPrice},
			#{priority},
			#{createTime},
			#{lastEditTime},
			#{enableStatus},
			#{productCategory.productCategoryId},
			#{shop.shopId}
		)
	</insert>
	
	
	<select id="selectProductById" resultMap="productMap" parameterType="Long">
		<!-- 具体的sql -->
		SELECT
			p.product_id,
			p.product_name,
			p.product_desc,
			p.img_addr,
			p.normal_price,
			p.promotion_price,
			p.priority,
			p.create_time,
			p.last_edit_time,
			p.enable_status,
			p.product_category_id,
			p.shop_id,
			pm.product_img_id,
			pm.img_addr,
			pm.img_desc,
			pm.priority,
			pm.create_time
		FROM
			tb_product p
		 <!-- 左连接LEFT JOIN,(即使该商品没有商品详情图片,也要查询出来该商铺) -->
		LEFT JOIN
			tb_product_img pm
		ON
			p.product_id =pm.product_id
		WHERE
			p.product_id = #{productId}
		ORDER BY
			pm.priority DESC
	</select>
	
	
	<update id="updateProduct" parameterType="com.artisan.o2o.entity.Product">
		UPDATE
			tb_product
		<set>
		<!-- 注意后面的逗号 -->
			<if test="productName !=null ">product_name = #{productName},</if>
			<if test="productDesc !=null ">product_desc = #{productDesc},</if>
			<if test="imgAddr !=null ">img_addr = #{imgAddr},</if>
			<if test="normalPrice != null ">normal_price = #{normalPrice},</if>
			<if test="promotionPrice != null ">promotion_price = #{promotionPrice},</if>
			<if test="priority != null">priority = #{priority},</if>
			<if test="createTime != null">create_time = #{createTime},</if>
			<if test="lastEditTime != null">last_edit_time = #{lastEditTime},</if>
			<if test="enableStatus != null ">enable_status = #{enableStatus},</if>
			<!-- 注意如果是引用的复杂对象的写法 -->
			<if test="productCategory != null and productCategory.productCategoryId != null ">product_category_id = #{productCategory.productCategoryId},</if>
		</set>
		WHERE
		 	product_id = #{productId}
		 AND 
			shop_id=#{shop.shopId}
	</update>
	
</mapper>    

ProductImgDao.xml

代码语言:javascript复制
<?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.artisan.o2o.dao.ProductImgDao">
	
	<insert id="batchInsertProductImg" 
		parameterType="com.artisan.o2o.entity.ProductImg" 
		useGeneratedKeys="true" keyProperty="productImgId" keyColumn="product_img_id">
		INSERT INTO
			tb_product_img
			(
				img_addr,
				img_desc,
				priority,
				create_time,
				product_id
			)
		VALUES
			<foreach collection="list" item="productImg" index="index"  separator=",">
				(
					#{productImg.imgAddr},
					#{productImg.imgDesc},
					#{productImg.priority},
					#{productImg.createTime},
					#{productImg.productId}
				)
			</foreach>
	</insert>
	
	
	
	<delete id="deleteProductImgById">
		DELETE FROM 
			tb_product_img 
		WHERE 
			product_id = #{produtId}
	</delete>

	
	<select id="selectProductImgList" resultType="com.artisan.o2o.entity.ProductImg">
		SELECT 
			product_img_id,
			img_addr,
			img_desc,
			priority,
			create_time,
			product_id
		FROM 
			tb_product_img
		WHERE 
			product_id=#{productId}
		ORDER BY  
			product_img_id 
	</select>
	
</mapper>  

单元测试

ProductDaoTest

代码语言:javascript复制
package com.artisan.o2o.dao;

import java.util.Date;

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.Product;
import com.artisan.o2o.entity.ProductCategory;
import com.artisan.o2o.entity.Shop;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ProductDaoTest extends BaseTest {

	@Autowired
	ProductDao productDao;

	@Test
	public void testA_InsertProdcut() {

		// 注意表中的外键关系,确保这些数据在对应的表中的存在
		ProductCategory productCategory = new ProductCategory();
		productCategory.setProductCategoryId(36L);

		// 注意表中的外键关系,确保这些数据在对应的表中的存在
		Shop shop = new Shop();
		shop.setShopId(5L);

		Product product = new Product();
		product.setProductName("test_product");
		product.setProductDesc("product desc");
		product.setImgAddr("/aaa/bbb");
		product.setNormalPrice("10");
		product.setPromotionPrice("8");
		product.setPriority(66);
		product.setCreateTime(new Date());
		product.setLastEditTime(new Date());
		product.setEnableStatus(1);
		product.setProductCategory(productCategory);
		product.setShop(shop);

		int effectNum = productDao.insertProduct(product);
		Assert.assertEquals(1, effectNum);
	}

	@Test
	public void testB_UpdateProduct() {

		// 注意表中的外键关系,确保这些数据在对应的表中的存在
		ProductCategory productCategory = new ProductCategory();
		productCategory.setProductCategoryId(36L);

		// 注意表中的外键关系,确保这些数据在对应的表中的存在
		Shop shop = new Shop();
		shop.setShopId(5L);
		
		Product product = new Product();
		product.setProductName("modifyProduct");
		product.setProductDesc("modifyProduct desc");
		product.setImgAddr("/mmm/ddd");
		product.setNormalPrice("350");
		product.setPromotionPrice("300");
		product.setPriority(66);
		product.setLastEditTime(new Date());
		product.setEnableStatus(1);

		product.setProductCategory(productCategory);
		product.setShop(shop);

		// 设置productId
		product.setProductId(2L);

		int effectNum = productDao.updateProduct(product);
		Assert.assertEquals(1, effectNum);

	}
}

ProductImgDaoTest

代码语言:javascript复制
package com.artisan.o2o.dao;

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

import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
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.ProductImg;

/**
 * 
 * 
 * @ClassName: ProductImgDaoTest
 * 
 * @Description: 测试类的执行顺序可通过对测试类添加注解@FixMethodOrder(value) 来指定
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年6月30日 下午3:28:28
 */
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ProductImgDaoTest extends BaseTest {

	@Autowired
	private ProductImgDao productImgDao;

	/**
	 * 加入@Ignore 可以不执行该单元测试方法
	 */
	@Test
	@Ignore
	public void testBatchInsertProductImg() {
		ProductImg productImg1 = new ProductImg();
		productImg1.setImgAddr("/xiaogongjiang/xxxx");
		productImg1.setImgDesc("商品详情图片1");
		productImg1.setPriority(99);
		productImg1.setCreateTime(new Date());
		productImg1.setProductId(2L);
		
		ProductImg productImg2 = new ProductImg();
		productImg2.setImgAddr("/artisan/xxxx");
		productImg2.setImgDesc("商品详情图片2");
		productImg2.setPriority(98);
		productImg2.setCreateTime(new Date());
		productImg2.setProductId(2L);

		// 添加到productImgList中
		List<ProductImg> productImgList = new ArrayList<ProductImg>();
		productImgList.add(productImg1);
		productImgList.add(productImg2);

		// 调用接口批量新增商品详情图片
		int effectNum = productImgDao.batchInsertProductImg(productImgList);
		Assert.assertEquals(2, effectNum);
	}

	@Test
	public void testA_BatchInsertProductImg() {
		ProductImg productImg1 = new ProductImg();
		productImg1.setImgAddr("/xxx/xxx");
		productImg1.setImgDesc("商品详情图片1x");
		productImg1.setPriority(88);
		productImg1.setCreateTime(new Date());
		productImg1.setProductId(3L);

		ProductImg productImg2 = new ProductImg();
		productImg2.setImgAddr("/yyy/yyyy");
		productImg2.setImgDesc("商品详情图片2y");
		productImg2.setPriority(66);
		productImg2.setCreateTime(new Date());
		productImg2.setProductId(3L);

		// 添加到productImgList中
		List<ProductImg> productImgList = new ArrayList<ProductImg>();
		productImgList.add(productImg1);
		productImgList.add(productImg2);

		// 调用接口批量新增商品详情图片
		int effectNum = productImgDao.batchInsertProductImg(productImgList);
		Assert.assertEquals(2, effectNum);
	}

	@Test
	public void testB_DeleteProductImgById() {
		Long productId = 3L;
		int effectNum = productImgDao.deleteProductImgById(productId);
		Assert.assertEquals(2, effectNum);
	}
}

单元测试通过.可以看到是按照方法名的升序顺序执行的,形成一个闭环。


SQL日志如下

代码语言:javascript复制
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@5bf8fa12] will not be managed by Spring
==>  Preparing: INSERT INTO tb_product_img ( img_addr, img_desc, priority, create_time, product_id ) VALUES ( ?, ?, ?, ?, ? ) , ( ?, ?, ?, ?, ? ) 
==> Parameters: /xxx/xxx(String), 商品详情图片1x(String), 88(Integer), 2018-06-30 21:26:34.455(Timestamp), 3(Long), /yyy/yyyy(String), 商品详情图片2y(String), 66(Integer), 2018-06-30 21:26:34.455(Timestamp), 3(Long)
<==    Updates: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7a67e3c6]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1921ad94] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@30af5b6b] will not be managed by Spring
==>  Preparing: SELECT product_img_id, img_addr, img_desc, priority, create_time, product_id FROM tb_product_img WHERE product_id=? ORDER BY product_img_id 
==> Parameters: 3(Long)
<==    Columns: product_img_id, img_addr, img_desc, priority, create_time, product_id
<==        Row: 16, /xxx/xxx, 商品详情图片1x, 88, 2018-06-30 21:26:34.0, 3
<==        Row: 17, /yyy/yyyy, 商品详情图片2y, 66, 2018-06-30 21:26:34.0, 3
<==      Total: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1921ad94]
ProductImg [productImgId=16, imgAddr=/xxx/xxx, imgDesc=商品详情图片1x, priority=88, createTime=Sat Jun 30 21:26:34 BOT 2018, productId=3]
ProductImg [productImgId=17, imgAddr=/yyy/yyyy, imgDesc=商品详情图片2y, priority=66, createTime=Sat Jun 30 21:26:34 BOT 2018, productId=3]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@535779e4] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6c0d9d86] will not be managed by Spring
==>  Preparing: DELETE FROM tb_product_img WHERE product_id = ? 
==> Parameters: 3(Long)
<==    Updates: 2
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@535779e4]

Github地址

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

0 人点赞