其他分享
首页 > 其他分享> > day71(添加类别--持久层,添加类别--业务逻辑层)

day71(添加类别--持久层,添加类别--业务逻辑层)

作者:互联网

day71(添加类别--持久层,添加类别--业务逻辑层)

1.类别管理--添加类别--持久层

1.配置

续前日,无新增

2.规划需要执行的SQL语句

续前日,无新增

3.接口与抽象方法

此前需要执行的SQL语句大致是

select id from pms_category where name=?

1.创建CategorySimpleVO类

在csmall-pojo的根包下创建vo.CategorySimpleVO类,用于封装以上查询结果:

@Data
public class CategorySimpleVO implements Serializable {
   private Long id;
}

2.添加抽象方法(在csmall-product-webapiCategoryMapper接口中)

CategorySimpleVO getByName(String name);

4.配置SQL语句

在csmall-product-webapi的CategoryMapper.xml中添加配置:

<!-- CategorySimpleVO getByName(String name); -->
<select id="getByName" resultMap="SimpleResultMap">
   select id from pms_category where name=#{name}
</select>

<resultMap id="SimpleResultMap" type="cn.tedu.csmall.pojo.vo.CategorySimpleVO">
   <id column="id" property="id" />
</resultMap>

5.测试

1.创建insert_data.sql文件(用于插入数据测试)

csmall-product-webapisrc\test\resources下创建insert_data.sql文件

insert into pms_category (name) value ('类别001'), ('类别002');

2.在CategoryMapperTests中添加测试方法:

@Test
@Sql({"classpath:truncate.sql","classpath:insert_data.sql"})
public void testGetByNameSuccessfully(){
   //测试数据
   String name="类别001";
   //断言不会抛出异常
   assertDoesNotThrow(()->{
       //执行查询
       CategorySimpleVO category=mapper.getByName(name);
       //断言查询结果为null
       assertNotNull(category);
  });
}
@Test
@Sql("classpath:truncate.sql")
public void testGetByNameFailBecauseNotFound(){
   //测试数据
   String name ="类别999";
   //断言不会抛出异常
   assertDoesNotThrow(()->{
       //执行查询
       CategorySimpleVO category=mapper.getByName(name);
       //断言查询结果为null
       assertNull(category);
  });
}

3.执行整个测试类

2.类别管理--添加类别--业务逻辑层

1.接口与抽象方法

1.建立专门存放业务逻辑层的接口的Module(名为:csmall-product-service)

2.配置(新Module下的pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <!-- 父级项目 -->
   <parent>
       <groupId>cn.tedu</groupId>
       <artifactId>csmall-product</artifactId>
       <version>0.0.1-SNAPSHOT</version>
   </parent>

   <!-- 当前项目的信息 -->
   <groupId>cn.tedu</groupId>
   <artifactId>csmall-product-service</artifactId>
   <version>0.0.1-SNAPSHOT</version>

   <!-- 当前项目需要使用的依赖项 -->
   <dependencies>
       <!-- Csmall POJO -->
       <dependency>
           <groupId>cn.tedu</groupId>
           <artifactId>csmall-pojo</artifactId>
       </dependency>
   </dependencies>

</project>

3.在csmall-product的pom.xml中补充子级Module

<!-- 当前Project的各子级Module -->
<modules>
   <module>csmall-product-webapi</module>
   <module>csmall-product-service</module> <!-- 新增 -->
</modules>

4.删除不必要文件

5.创建接口并添加抽象方法

1.方法的参数应该是封装的对象(因为一个StringLong等简单数据不足以完成添加类别的操作)

2.创建dto.CategoryAddNewDTO类(在csmall-pojo的根包下)

package cn.tedu.csmall.pojo.dto;

import lombok.Data;

import java.io.Serializable;

@Data
public class CategoryAddNewDTO implements Serializable {

   private String name;
   private Long parentId;
   private String keywords;
   private Integer sort;
   private String icon;
   private Integer isDisplay;

}

3.创建接口(CategoryService接口)

csmall-product-service中,在cn.tedu.csmall.product.service下创建ICategoryService接口:

public interface ICategoryService {
   void addNew(CategoryAddNewDTO categoryAddNewDTO);
}

2.实现

1.方法

  1. 因为在csmall-product-service中只能存放业务逻辑层的接口

  2. 业务逻辑层的实现类仍在csmall-product-webapi中。

  3. 因此,需要在csmall-product-webapi中依赖csmall-product-service

2.步骤

1.在Project的pom.xml中添加对csmall-product-service的依赖管理:

<!-- ===== 原有其它代码 ===== -->

<!-- 依赖管理,主要管理各依赖项的版本,使得子级Module添加依赖时不必指定版本 -->
<dependencyManagement>
   <dependencies>
       <!-- Csmall Product Service -->
       <dependency>
           <groupId>cn.tedu</groupId>
           <artifactId>csmall-product-service</artifactId>
           <version>${csmall.version}</version>
       </dependency>
       
       <!-- ===== 原有其它代码 ===== -->

2.在csmall-product-webapi中添加依赖:

<!-- ===== 原有其它代码 ===== -->

<!-- 当前项目需要使用的依赖项 -->
<dependencies>
   <!-- Csmall Product Service -->
   <dependency>
       <groupId>cn.tedu</groupId>
       <artifactId>csmall-product-service</artifactId>
   </dependency>
   
   <!-- ===== 原有其它代码 ===== -->

3.创建service.CategoryServiceImpl类:实现ICategoryService接口,添加

@Service注解(在cn.tedu.csmall.product.webapi下)

package cn.tedu.csmall.product.webapi.service;

import cn.tedu.csmall.pojo.dto.CategoryAddNewDTO;
import cn.tedu.csmall.product.service.ICategoryService;
import org.springframework.stereotype.Service;

@Service
public class CategoryServiceImpl implements ICategoryService {
   
   @Override
   public void addNew(CategoryAddNewDTO categoryAddNewDTO) {
  }
   
}

4.业务分析

@Autowired
private CategoryMapper categoryMapper;
//注意:需要在categoryMapper中补充getById()方法,至少返回depthd
//注意:需要创建异常
public void addNew(CategoryAddNewDTO categoryAddNewDTO){
   //从参数中尝试获取添加的类别的名称
   //在category中调用getByName方法,判断是否为null
   //是,抛出异常serviceException
   
   //从参数中取出父级类别id:parentId
   //判断parentId是否为0
   //是,那么不存在父级,则为一级类别,当前depth=1
   //否,那么存在父级,调用categoryMapper.getById()方法查询父级类别的信息
 
   //判断查询结果是否为null
   //是:抛出异常:serviceException
   //否:当前depth=>父级depth+1
   //创建category对象
   //调用beanUtils.copyProperties()将参数对象中的属性值复制到category对象中
   // 补全Category对象中的属性值:depth >>> 前序运算结果
   // 补全Category对象中的属性值:enable >>> 1(默认即启用)
   // 补全Category对象中的属性值:isParent >>> 0
   // 补全Category对象中的属性值:gmtCreate, gmtModified >>> LocalDateTime.now()
   //调用categoryMapper.insert(category)插入数据,返回受影响的行数
   //判断行数是否不为1
   //是:抛出异常serviceException
   
}
1.实现(根据id查询类别信息)
  1. 要实现以上业务,需要先在持久层完成“根据id查询类别信息”的功能,则在CategorySimpleVO中添加private Integer depth;属性(原getByName()方法对应的查询也作对应的修改,虽然不是必须的)。

  2. 添加private Integer isParent;属性(在CategorySimpleVO中),并且,必须在接下的查询中,查出此值。

  3. CategeoryMapper接口中添加:

    CategorySimpleVO getById(Long id);
  4. CategoryMapper.xml中配置以上方法映射的SQL:

    <!-- CategorySimpleVO getById(Long id); -->
    <select id="getById" resultMap="SimpleResultMap">
       select id, depth from pms_category where id=#{id}
    </select>
  5. 测试(CategoryMapperTests)

    @Test
    @Sql({"classpath:truncate.sql", "classpath:insert_data.sql"})
    public void testGetByIdSuccessfully() {
       // 测试数据
       Long id = 1L;
       // 断言不会抛出异常
       assertDoesNotThrow(() -> {
           // 执行查询
           CategorySimpleVO category = mapper.getById(id);
           // 断言查询结果不为null
           assertNotNull(category);
      });
    }

    @Test
    @Sql({"classpath:truncate.sql"})
    public void testGetByIdFailBecauseNotFound() {
       // 测试数据
       Long id = -1L;
       // 断言不会抛出异常
       assertDoesNotThrow(() -> {
           // 执行查询
           CategorySimpleVO category = mapper.getById(id);
           // 断言查询结果为null
           assertNull(category);
      });
    }
  6. CategoryMapper接口中添加:

    int updateIsParentById(@Param("id") Long id, @Param("isParent") Integer isParent);
  7. CategoryMapper.xml中配置以上方法映射的SQL:

    <!-- int updateIsParentById(@Param("id") Long id, @Param("isParent") Integer isParent); -->
    <update id="updateIsParentById">
       update pms_category set is_parent=#{isParent} where id=#{id}
    </update>
  8. 测试(CategoryMapperTests)

    @Test
    @Sql({"classpath:truncate.sql", "classpath:insert_data.sql"})
    public void testUpdateIsParentByIdSuccessfully() {
       // 测试数据
       Long id = 1L;
       Integer isParent = 1;
       // 断言不会抛出异常
       assertDoesNotThrow(() -> {
           // 执行测试
           int rows = mapper.updateIsParentById(id, isParent);
           // 断言受影响的行数为1
           assertEquals(1, rows);
      });
    }

    @Test
    @Sql({"classpath:truncate.sql"})
    public void testUpdateIsParentByIdFailBecauseNotFound() {
       // 测试数据
       Long id = -1L;
       Integer isParent = 1;
       // 断言不会抛出异常
       assertDoesNotThrow(() -> {
           // 执行测试
           int rows = mapper.updateIsParentById(id, isParent);
           // 断言受影响的行数为0
           assertEquals(0, rows);
      });
    }

5.自定义异常类型(创建csmall-commonModule)

原因:

由于后续还有不少需要被多个Module共同使用的类、接口等,所以,此异常类型和后续可能被共用的类、接口都应该放在一个公共的Module中,则在Project下创建csmall-common这个新的Module,创建成功后,需要:

1.创建ex.ServiceException类
public class ServiceException extends RuntimeException {
// 暂时不加构造方法
}

6.实现业务(在csmall-product-webapi中的CategoryServiceImpl)

package cn.tedu.csmall.product.webapi.service;

import cn.tedu.csmall.common.ex.ServiceException;
import cn.tedu.csmall.pojo.dto.CategoryAddNewDTO;
import cn.tedu.csmall.pojo.entity.Category;
import cn.tedu.csmall.pojo.vo.CategorySimpleVO;
import cn.tedu.csmall.product.service.ICategoryService;
import cn.tedu.csmall.product.webapi.mapper.CategoryMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Service
public class CategoryServiceImpl implements ICategoryService {

   @Autowired
   CategoryMapper categoryMapper;

   @Override
   public void addNew(CategoryAddNewDTO categoryAddNewDTO) {
       // 从参数中取出尝试添加的类别的名称
       String name = categoryAddNewDTO.getName();
       // 调用categoryMapper.getByName()方法查询
       CategorySimpleVO queryResult = categoryMapper.getByName(name);
       // 判断查询结果是否不为null
       if (queryResult != null) {
           // 是:抛出ServiceException
           throw new ServiceException();
      }

       // 从参数中取出父级类别的id:parentId
       Long parentId = categoryAddNewDTO.getParentId();
       // 判断parentId是否为0,当前尝试新增的类别的depth默认为1
       Integer depth = 1;
       CategorySimpleVO parentCategory = null;
       if (parentId != 0) {
           // 否:此次尝试添加的不是一级类别,则应该存在父级类别,调用categoryMapper.getById()方法查询父级类别的信息
           parentCategory = categoryMapper.getById(parentId);
           // -- 判断查询结果是否为null
           if (parentCategory == null) {
               // -- 是:抛出ServiceException
               throw new ServiceException();
          }
           // -- 否:当前depth >>> 父级depth + 1
           depth = parentCategory.getDepth() + 1;
      }

       // 创建Category对象
       Category category = new Category();
       // 调用BeanUtils.copyProperties()将参数对象中的属性值复制到Category对象中
       BeanUtils.copyProperties(categoryAddNewDTO, category);
       // 补全Category对象中的属性值:depth >>> 前序运算结果
       category.setDepth(depth);
       // 补全Category对象中的属性值:enable >>> 1(默认即启用)
       category.setEnable(1);
       // 补全Category对象中的属性值:isParent >>> 0
       category.setIsParent(0);
       // 补全Category对象中的属性值:gmtCreate, gmtModified >>> LocalDateTime.now()
       LocalDateTime now = LocalDateTime.now();
       category.setGmtCreate(now);
       category.setGmtModified(now);
       // 调用categoryMapper.insert(Category)插入类别数据,获取返回的受影响的行数
       int rows = categoryMapper.insert(category);
       // 判断返回的受影响的行数是否不为1
       if (rows != 1) {
           // 是:抛出ServiceException
           throw new ServiceException();
      }

       // 判断父级类别的isParent是否为0
       // 以下判断条件有部分多余,但不会报错
       if (parentId != 0 && parentCategory != null && parentCategory.getIsParent() == 0) {
           // 是:调用categoryMapper.updateIsParentById()方法,将父级类别的isParent修改为1,获取返回的受影响的行数
           rows = categoryMapper.updateIsParentById(parentId, 1);
           // 判断返回的受影响的行数是否不为1
           if (rows != 1) {
               // 是:抛出ServiceException
               throw new ServiceException();
          }
      }
  }

}

7.测试(在src/test/java下的根包下创建service.CategoryServiceTests测试类)

package cn.tedu.csmall.product.webapi.service;

import cn.tedu.csmall.common.ex.ServiceException;
import cn.tedu.csmall.pojo.dto.CategoryAddNewDTO;
import cn.tedu.csmall.product.service.ICategoryService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.jdbc.Sql;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
public class CategoryServiceTests {

   @Autowired
   ICategoryService service;

   @Test
   @Sql("classpath:truncate.sql")
   public void testAddNewSuccessfully() {
       // 测试数据
       CategoryAddNewDTO category = new CategoryAddNewDTO();
       category.setName("大屏智能手机");
       category.setParentId(0L);
       category.setIcon("未上传类别图标");
       category.setKeywords("未设置关键字");
       category.setSort(88);
       category.setIsDisplay(1);
       // 断言不会抛出异常
       assertDoesNotThrow(() -> {
           // 执行测试
           service.addNew(category);
      });
  }

   @Test
   @Sql({"classpath:truncate.sql", "classpath:insert_data.sql"})
   public void testAddNewFailBecauseNameDuplicate() {
       // 测试数据
       CategoryAddNewDTO category = new CategoryAddNewDTO();
       category.setName("类别001");
       // 断言不会抛出异常
       assertThrows(ServiceException.class, () -> {
           // 执行测试
           service.addNew(category);
      });
  }

   @Test
   @Sql({"classpath:truncate.sql"})
   public void testAddNewFailBecauseParentNotFound() {
       // 测试数据
       CategoryAddNewDTO category = new CategoryAddNewDTO();
       category.setName("类别001");
       category.setParentId(-1L);
       // 断言不会抛出异常
       assertThrows(ServiceException.class, () -> {
           // 执行测试
           service.addNew(category);
      });
  }

}
 

标签:category,product,cn,--,添加,csmall,类别,import,id
来源: https://www.cnblogs.com/xiaoyezilei/p/16366924.html