为什么传入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是 “加工好的成品”—— 前端不需要原材料,只需要能直接显示的成品。
 

总结(核心关键点)

 
  1. DTO 分工:OrdersPageQueryDTO是 “查询条件”,OrdersDTO是 “返回结果”,前者给后端传条件,后者给前端返数据;
  2. collection 作用:MyBatis 通过它实现 “订单→多个详情” 的一对多映射,自动查详情并塞到 OrdersDTO 里;
  3. ResultMap 核心:关联查询的结果能变成 OrdersDTO,全靠 ResultMap 定义的 “数据库字段→DTO 字段” 的映射规则。
posted on 2026-01-07 10:59  fafrkvit  阅读(28)  评论(0)    收藏  举报