# 分页汇总功能使用说明 本文档介绍如何在平台项目中启用分页接口的汇总行(SUM)统计能力。该能力基于 `PageResult` 返回体与 `@PageSum` 标注,在分页查询时自动计算并返回指定字段的合计值。 ## 适用场景 - 需要在分页列表底部展示金额、数量等合计值。 - 希望后端自动补充汇总信息,避免前端手动累加。 - 已使用 `BaseMapperX` 及其 `selectPage` 等分页便捷方法。 ## 功能概览 | 组件 | 位置 | 作用 | | --- | --- | --- | | `@PageSum` | `com.zt.plat.framework.common.annotation.PageSum` | 标注需要参与 SUM 聚合的实体字段 | | `PageResult.summary` | `com.zt.plat.framework.common.pojo.PageResult` | 承载字段 -> `BigDecimal` 的汇总结果 | | `PageSumSupport` | `com.zt.plat.framework.mybatis.core.sum.PageSumSupport` | 负责扫描注解、克隆查询条件并执行 SUM 查询 | | `BaseMapperX.selectPage` | `com.zt.plat.framework.mybatis.core.mapper.BaseMapperX` | 在分页与非分页查询后自动附加汇总信息 | ## 接入步骤 ### 1. 在实体上标注 `@PageSum` ```java @TableName("order_summary") public class OrderSummaryDO { private Long id; @PageSum private BigDecimal amount; @PageSum(column = "tax_amount") private BigDecimal tax; @PageSum(column = "discount") private BigDecimal discountSummary; // 其它字段 ... } ``` - 不传 `column` 时,默认使用 MyBatis-Plus 实体字段映射的数据库列。 - 如需跨表或函数(例如 `sum(price * quantity)`),可在 `column` 中直接写 SQL 片段。 - 必须是数值类型(`Number`、`BigDecimal`、原生数值)。非数值字段会被忽略并打印警告日志。 - 对于并不存在于表中的“汇总专用字段”,仅需在 `@PageSum` 中声明 `exist = false`,框架会自动注入等效的 `@TableField(exist = false)`,无需再次编写 `@TableField` 注解。 ### 2. 使用 `BaseMapperX` 的分页能力 ```java PageResult page = orderSummaryMapper.selectPage(pageParam, wrapper); ``` - 仅 `BaseMapperX.selectPage`(含排序参数版本)支持自动附加汇总结果。 - 对于 `PageParam.PAGE_SIZE_NONE`(不分页)场景同样有效。 - `selectJoinPage` 暂未附加汇总信息,如需支持请二次封装。 > ⚠️ 目前的汇总增强依赖 MyBatis-Plus 默认分页(单表/简单条件)实现聚合。若需在复杂联表或高度自定义 SQL 中进行统计,请单独编写汇总接口,或在自定义逻辑中手工调用 `PageSumSupport.tryAttachSummary(...)`,避免影响现有查询语句。 ### 3. 暴露响应结果 `PageResult` 现在包含两个与数量相关的属性: - `total`:分页总数量,仍通过 `total` 字段返回(向后兼容 `totalCount` 反序列化)。 - `summary`:Map 结构,键为实体字段名,值为 `BigDecimal` 类型的合计值。 示例响应: ```json { "code": 0, "data": { "list": [ { "id": 1, "amount": 20.00, "tax": 1.20 }, { "id": 2, "amount": 30.00, "tax": 1.80 } ], "total": 2, "summary": { "amount": 50.00, "tax": 3.00 } } } ``` 前端即可直接读取 `data.summary.amount` 展示汇总行,无需手工聚合。 ## 常见问题 ### 汇总结果为空 - 检查实体字段是否正确标注 `@PageSum`,且类型为数值。 - 确认 Mapper 的泛型实体与查询结果实体一致,`PageSumSupport` 会基于 Mapper 泛型解析实体类型。 - 若查询条件覆盖了 `select` 列表(如显式调用 `select(...)`),请确保 SUM 语句仍能执行;`PageSumSupport` 会克隆 Wrapper 并重新设置 `select` 列表,手写 SQL 需保证兼容。 ### 自定义 SQL & 复杂场景 - 对于需要复杂汇总(如 CASE WHEN),可在 `column` 属性中写 SQL 表达式: ```java @PageSum(column = "SUM(CASE WHEN status = 'PAID' THEN amount ELSE 0 END)") private BigDecimal paidAmount; ``` - 当前实现 **仅会扫描 Mapper 泛型实体类** 上的 `@PageSum` 标注。若分页接口最终返回 VO,请先在实体上完成标注,再使用 `PageResult.convert(...)` 或其它方式将数据转换为 VO;转换后 `summary` 内容会被完整保留。 ### 非 BaseMapperX 查询 - 目前自动聚合只对 `BaseMapperX.selectPage` 及分页列表查询有效。 - 若使用 XML 自定义 SQL,可在逻辑中手动调用 `PageSumSupport.tryAttachSummary(mapper, wrapper, pageResult)`。 ## 调试与测试 - 单元测试示例:`com.zt.plat.framework.mybatis.core.sum.PageSumSupportTest`。 - 运行 `mvn -pl zt-framework/zt-spring-boot-starter-mybatis -am test` 可验证功能和回归。 - 日志中会输出数字解析或字段配置异常的告警信息,便于定位问题。 ## 变更兼容性 - `PageResult` 仍通过 `list`/`total` 提供原有分页数据,向后兼容旧接口。 - 新增 `summary` 字段,前端可按需展示。 - `totalCount` Setter / Getter 仍保留(`@JsonIgnore`),可兼容旧代码逻辑。 如需进一步扩展(例如 AVG、MAX 等聚合),可按现有结构在 `PageSumSupport` 基础上新增注解与聚合逻辑。