JavaWeb后端基础(5)
这一篇主要是web中数据库操作SQL语句怎么写的 多表关系(1对多 1对1 多对多) 以及多表查询(内连接、外连接、子查询)这篇我会重点记一下分页查询。
分页查询
我觉得最重要的就是要明白前端能给你什么参数,以及你返回给前端的是什么参数
后台给前端返回的数据包含:List集合(数据列表)、total(总记录数)。而这两部分我们通常封装到PageResult对象中,并将该对象转换为json格式的数据响应回给浏览器。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageResult {
private Long total; //总记录数
private List rows; //当前页数据列表
}
我们先只考虑分页查询 不考虑查询条件
@Slf4j
@RequestMapping("/emps")
@RestController
public class EmpController {
@Autowired
private EmpService empService;
@GetMapping
public Result page(@RequestParam(defaultValue = "1") Integer page ,
@RequestParam(defaultValue = "10") Integer pageSize){
log.info("查询员工信息, page={}, pageSize={}", page, pageSize);
PageResult pageResult = empService.page(page, pageSize);
return Result.success(pageBean);
}
}
@RequestParam
@RequestParam 括号里可以设置的参数有以下几个:
value 或 name 指定请求中参数的名称。如果不写,默认使用方法参数的名称
@RequestParam("username") String name
required 指定该参数是否必须,默认值是 true。如果设为 false,参数可选,缺失时值为 null 或默认值
@RequestParam(value = "age", required = false) Integer age
defaultValue指定参数缺失时的默认值。如果设置了默认值,required 会隐式变为 false
@RequestParam(value = "page", defaultValue = "1") int page
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Override
public PageResult page(Integer page, Integer pageSize) {
//1. 获取总记录数
Long total = empMapper.count();
//2. 获取结果列表
Integer start = (page - 1) * pageSize;
List<Emp> empList = empMapper.list(start, pageSize);
//3. 封装结果
return new PageResult(total, empList);
}
}
PageHelper分页插件
分页查询的思路、步骤是比较固定的。 在Mapper接口中定义两个方法执行两条不同的SQL语句:
-
查询总记录数
-
指定页码的数据列表
在Service当中,调用Mapper接口的两个方法,分别获取:总记录数、查询结果列表,然后在将获取的数据结果封装到PageBean对象中。
如果使用PageHelper插件
-
Mapper接口层:
-
原始的分页查询功能中,我们需要在Mapper接口中定义两条SQL语句。
-
PageHelper实现分页查询之后,只需要编写一条SQL语句,而且不需要考虑分页操作,就是一条正常的查询语句。
-
-
Service层:
-
需要根据页码、每页展示记录数,手动的计算起始索引。
-
无需手动计算起始索引,直接告诉PageHelper需要查询那一页的数据,每页展示多少条记录即可。
-
@Override
public PageResult page(Integer page, Integer pageSize) {
//1. 设置分页参数
PageHelper.startPage(page,pageSize);
//2. 执行查询
List<Emp> empList = empMapper.list();
Page<Emp> p = (Page<Emp>) empList;
//3. 封装结果
return new PageResult(p.getTotal(), p.getResult());
}
实现机制:
执行了两条SQL语句,而这两条SQL语句,其实是从我们在Mapper接口中定义的SQL演变而来的
其实就是将我们编写的SQL语句进行的改造增强,将查询返回的字段列表替换成了 count(0)
来统计总记录数
第二条SQL语句,用来进行分页查询,查询指定页码对应 的数据列表。
其实就是将我们编写的SQL语句进行的改造增强,在SQL语句之后拼接上了limit进行分页查询,而由于测试时查询的是第一页,起始索引是0,所以简写为limit ?
而PageHelper在进行分页查询时,会执行上述两条SQL语句,并将查询到的总记录数,与数据列表封装到了 Page<Emp>
对象中,我们再获取查询结果时,只需要调用Page对象的方法就可以获取
注意:
-
PageHelper实现分页查询时,SQL语句的结尾一定一定一定不要加分号(;).。
-
PageHelper只会对紧跟在其后的第一条SQL语句进行分页处理。
条件分页查询
主要是看一下SQL语句怎么写的
<!--定义Mapper映射文件的约束和基本结构-->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<select id="list" resultType="com.itheima.pojo.Emp">
select e.*, d.name deptName from emp as e left join dept as d on e.dept_id = d.id
<where>
<if test="name != null and name != ''">
e.name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and e.gender = #{gender}
</if>
<if test="begin != null and end != null">
and e.entry_date between #{begin} and #{end}
</if>
</where>
</select>
</mapper>
<if>
:判断条件是否成立,如果条件为true,则拼接SQL。
<where>
:根据查询条件,来生成where关键字,并会自动去除条件前面多余的and或or
所谓动态SQL,指的就是随着用户的输入或外部的条件的变化而变化的SQL语句
补充:
当我们在测试的时候,页码输入负数,查询是有问题的,查不到对应的数据了
那其实在PageHelper中,我们可以通过合理化参数配置,来解决这个问题。直接在application.yml中,引入如下配置即可:
pagehelper:
reasonable: true
helper-dialect: mysql