为什么传入OrdersPageQueryDTO,返回Page<OrdersDTO>?
这是典型的 **“查询条件 DTO” 和 “查询结果 DTO” 的分工 **,核心是 “各司其职”:
1. OrdersPageQueryDTO(入参):封装 “查询条件”
你可以把它理解为「前端给后端的 “搜索指令”」:
- 里面的字段(
page/pageSize/status/userId)都是筛选 / 分页条件(比如 “第 1 页、每页 10 条、查待付款订单”); - 作用:把前端零散的查询参数(page=1&pageSize=10&status=1)封装成一个 Java 对象,代码更整洁,避免方法参数过多;
- 类比:去奶茶店点单,
OrdersPageQueryDTO就是你说的 “要 1 杯珍珠奶茶、少糖、去冰”—— 只是 “需求”,不是 “最终拿到的奶茶”。
2. Page<OrdersDTO>(返回值):封装 “查询结果”
OrdersDTO:是「后端给前端的 “定制化数据包”」—— 和数据库的orders表实体(Orders)不同,OrdersDTO是为前端量身定制的(比如包含userName、orderDetailList等前端需要的字段,而Orders只对应数据库表字段);Page:是 PageHelper 分页插件的封装对象,包含total(总条数)和records(当前页数据),刚好匹配接口文档要求的data.total和data.records;- 类比:
Page<OrdersDTO>就是你最终拿到的 “奶茶 + 小票”—— 小票是total(总共有多少杯),奶茶是records里的OrdersDTO(包含你要的少糖、去冰等定制化属性)。
Page<OrdersDTO> page = orderMapper.pageQuery(ordersPageQueryDTO);
这句代码的意思是:把前端的查询条件(ordersPageQueryDTO)传给 MyBatis,MyBatis 执行对应的 SQL,然后把查询结果按照 ResultMap 的规则封装成 OrdersDTO 对象,再用 Page 包装成分页结果。
二、collection标签的关键字含义(MyBatis 一对多映射核心)
<collection>是 MyBatis 专门处理「一对多」关系的标签(一个订单对应多个订单详情),里面的每个属性都是 “映射规则”:<collection
property="orderDetailList" <!-- 规则1:往OrdersDTO的哪个字段塞数据 -->
ofType="com.sky.entity.OrderDetail" <!-- 规则2:集合里的元素类型是什么 -->
select="com.sky.mapper.OrderDetialMapper.getByOrderId" <!-- 规则3:用哪个方法查详情 -->
column="id"/> <!-- 规则4:给查详情的方法传什么参数 -->
执行流程:
MyBatis 先查完订单主数据(orders 表),然后自动拿着每个订单的 id,调用
OrderDetialMapper.getByOrderId(id)查询该订单的所有详情,最后把详情列表塞进OrdersDTO的orderDetailList字段里。三、为什么关联查询(orders+user)后,结果变成了OrdersDTO?
1. 先看 SQL 查询的原始数据:
核心是ResultMap 的 “映射规则” 在起作用——MyBatis 不会自动返回任意对象,而是严格按照你定义的
ResultMap来封装数据:select
o.*, -- orders表的所有字段(id、number、status、user_id...)
u.name as user_name -- user表的name字段,别名user_name
from orders o
left join user u on o.user_id = u.id
执行后,数据库返回的是「订单字段 + 用户名」的原始数据(比如:id=14、number=1767683845143、user_id=4、user_name = 测试用户...)。
2. ResultMap 定义 “原始数据→OrdersDTO” 的映射规则:
<resultMap id="BaseOrdersResultMap" type="com.sky.dto.OrdersDTO">
<id column="id" property="id"/> <!-- 数据库的id → OrdersDTO的id -->
<result column="number" property="number"/> <!-- 数据库的number → OrdersDTO的number -->
<result column="user_name" property="userName"/> <!-- 数据库的user_name → OrdersDTO的userName -->
<!-- 其他字段同理:数据库字段 → OrdersDTO字段 -->
</resultMap>
type="com.sky.dto.OrdersDTO":明确告诉 MyBatis—— 把查询结果封装成OrdersDTO对象,而不是Orders实体;- 每个
<result>标签:定义 “数据库字段(column)” 和 “OrdersDTO 字段(property)” 的对应关系。
3. 核心结论:
不是 “关联查询导致变成 OrdersDTO”,而是你在
<select>标签里指定了resultMap="OrdersWithDetailResultMap",这个 ResultMap 的type是OrdersDTO,所以 MyBatis 会强制把查询结果封装成OrdersDTO。补充:为什么不用Orders实体,而用OrdersDTO?
Orders:是和数据库orders表一一对应的实体(只包含表中字段,比如没有userName、orderDetailList);OrdersDTO:是为前端定制的传输对象(包含前端需要的所有字段:比如关联用户表的userName、一对多的orderDetailList);- 类比:
Orders是 “仓库里的原材料”,OrdersDTO是 “加工好的成品”—— 前端不需要原材料,只需要能直接显示的成品。
总结(核心关键点)
- DTO 分工:
OrdersPageQueryDTO是 “查询条件”,OrdersDTO是 “返回结果”,前者给后端传条件,后者给前端返数据; - collection 作用:MyBatis 通过它实现 “订单→多个详情” 的一对多映射,自动查详情并塞到 OrdersDTO 里;
- ResultMap 核心:关联查询的结果能变成 OrdersDTO,全靠 ResultMap 定义的 “数据库字段→DTO 字段” 的映射规则。
浙公网安备 33010602011771号