概要
完成两个模块的功能:员工管理模块、分类管理模块。两个模块换汤不换药,具体的逻辑流程都差不多。
整体架构流程
在完成某一个模块的时候流程:
- 直接利用Yapi接口文档,分析我们后端需要完成的业务逻辑,需要传递一些什么数据(比如是需要传递一个DTO对象好,还是传递一些普通形参好)
- 分析好之后,我们需要将这个模块的三层架构先搭建好,controller,Service,Mapper层,把需要的对象都注入进去(“访问路径注解”,“自动注入注解”,“接口文档注解”,这里我容易忘记@RequestBody注解,导致拿不到数据)
- 三层架构搭建好之后,看接口文档前端传进来的数据,来决定我们最后Mapper层的用什么对象或者属性来交互,其余就是对业务逻辑Service层的“装点和修饰”。
技术细节
1.分页插件使用的流程:
在Servcie层分为了3个步骤:
(1)利用插件实现分页:
PageHelper.startPage(pageNum, pageSize);
分页库的这个对象里面的常用两个方法:
getTotal():
功能: 返回总记录数。
方法示例:long total = page.getTotal();
getResult():
功能: 直接可以用 List<T> 来获取当前页的数据,通常使用 getResult() 方法在 Page 对象中并不存在。
获取当前页数据:List<Employee> employees = page.getResult();
(2)利用查询语句查询数据:
List<User> users = userMapper.selectAllUsers();
1,2步骤一结合就出现我们数据最用分页的效果,我个人了理解,先实现分页,然后再将数据填充进去。分成两步而已
(3)最终返回分页的数据对象:
return new PageInfo<>(users);
完整代码:
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public PageInfo<User> getUsers(int pageNum, int pageSize) {
// 开始分页 pageNum是当前页面 pagesize是当前一页有多少条数据
PageHelper.startPage(pageNum, pageSize);
// 查询所有用户
List<User> users = userMapper.selectAllUsers();
// 封装分页结果
return new PageInfo<>(users);
}
}
2.Mapper层增删改查的细节:
(1)思维技巧:SQL 查询中使用 CONCAT 函数来拼接字符串,灵活性:使用 CONCAT 更灵活,适合动态构建查询条件,或者模糊匹配搜索。
<select id="pageQuery" resultType="com.sky.entity.Employee">
select * from employee
<where>
<if test="name != null and name != ''">
and name like concat('%',#{name},'%')
</if>
</where>
order by create_time desc
</select>
(2).一个模块下:不同接口的访问路径我现在理解了是怎么设计的了:
(个人理解)打个分类模块的比方:
POST /categories 用于新增分类。
GET /categories 用于获取分类列表。
PUT /categories/{id} 用于更新特定 ID 的分类
DELETE /categories/{id} 用于删除分类。
这种Rest风格理解:为了保持直观简洁,“增删改查”尽量只是改写前面的“模块的名称”
比如这里分类模块的: “category”, 后面斜杠“/”后边是否有参数,则是根据业务逻辑决定的,比如我们的“增”就没必要携带参数,但是删改查,可能就需要了。
(3).知识盲区:Mapper层的查询语句,返回的对象是有讲究的。
返回单条记录和多条记录:一个是一个对象,一个是一个集合
@Mapper
public interface CategoryMapper {
// 期望返回单条记录
@Select("SELECT * FROM category WHERE id = #{id}")
Category getCategoryById(long id); // 使用 selectOne()
// 期望返回多条记录
@Select("SELECT * FROM category WHERE type = #{type}")
List<Category> getCategoriesByType(String type); // 使用 selectList()
}
(4)Mybatis的查询和删除必须要有返回值,其余两个可以不用返回值,那两个如果写接口的时候没有返回值就会报错
小结and意外收获
1.小结:
- 入门,我觉得不用去想这些类是怎么设计的,为什么需要有这样那样的属性,那是架构师,分析师,“leader”负责的,我们只是码农,只负责完成前端的数据和数据库之间的数据进行交互
- 我们要看前端有时候给的查询条件是什么,不要自定义查询的条件,比如修改分类:通过name,自己却自定义了一个:id,后边发现数据对接不了就白忙活了。