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-webapi
的CategoryMapper
接口中)
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-webapi
的src\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.删除不必要文件
-
启动类
-
src\main\resources
及其下的配置文件 -
src\test
5.创建接口并添加抽象方法
1.方法的参数应该是封装的对象(因为一个String
或Long
等简单数据不足以完成添加类别的操作)
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.方法
-
因为在csmall-product-service中只能存放业务逻辑层的接口
-
业务逻辑层的实现类仍在csmall-product-webapi中。
-
因此,需要在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查询类别信息)
-
要实现以上业务,需要先在持久层完成“根据id查询类别信息”的功能,则在CategorySimpleVO中添加private Integer depth;属性(原
getByName()
方法对应的查询也作对应的修改,虽然不是必须的)。 -
添加private Integer isParent;属性(在CategorySimpleVO中),并且,必须在接下的查询中,查出此值。
-
CategeoryMapper接口中添加:
CategorySimpleVO getById(Long id);
-
在CategoryMapper.xml中配置以上方法映射的SQL:
<!-- CategorySimpleVO getById(Long id); -->
<select id="getById" resultMap="SimpleResultMap">
select id, depth from pms_category where id=#{id}
</select> -
测试(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);
});
} -
在CategoryMapper接口中添加:
int updateIsParentById(@Param("id") Long id, @Param("isParent") Integer isParent);
-
在
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> -
测试(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,创建成功后,需要:
-
在
csmall-common
中,修改pom.xml
中的父项目 -
在
csmall-common
中,在pom.xml
删除依赖项 -
在
csmall-common
中,在pom.xml
删除<build>
配置 -
在
csmall-common
中,删除src/test
-
在
csmall-common
中,删除src/main/resources
-
在
csmall-common
中,删除启动类 -
在Project的
pom.xml
中,添加<module>
-
在Project的
pom.xml
中,添加对新Module的依赖管理 -
在
csmall-product-webapi
中的pom.xml
中,添加对csmall-common
的依赖
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