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

概述

完成了商品的添加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<ProductImg> ,然后遍历该list,获取集合中每个ProductImg的imgAddr地址,所以还需要有个selectProductImgList方法

Dao层接口

ProductDao#selectProductById

/**
     * 
     * 
     * @Title: selectProductById
     * 
     * @Description: 根据productId查询product
     * 
     * @param productId
     * 
     * @return: Product
     */
    Product selectProductById(long productId);

ProductDao#updateProduct

/**
     * 
     * 
     * @Title: updateProduct
     * 
     * @Description: 修改商品
     * 
     * @param product
     * 
     * @return: int
     */
    int updateProduct(Product product);

ProductImgDao#deleteProductImgById

/**
     * 
     * 
     * @Title: deleteProductImgById
     * 
     * @Description: 删除商品对应的商品详情图片
     * 
     * @param productId
     * 
     * @return: int
     */
    int deleteProductImgById(long productId);

ProductImgDao#selectProductImgList

    /**
     * 
     * 
     * @Title: selectProductImgList
     * 
     * @Description: 根据productId查询商铺对应的图片详情信息
     * 
     * @param productId
     * 
     * @return: List<ProductImg>
     */
    List<ProductImg> selectProductImgList(long productId);

Mapper映射文件

ProductDao.xml

说明见注释

<?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

<?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

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

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日志如下

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

猜你喜欢

转载自blog.csdn.net/yangshangwei/article/details/80871693