125 lines
5.1 KiB
Markdown
125 lines
5.1 KiB
Markdown
# 分页汇总功能使用说明
|
||
|
||
本文档介绍如何在平台项目中启用分页接口的汇总行(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<OrderSummaryRespVO> 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` 基础上新增注解与聚合逻辑。
|