3.3 分页排序与结果映射
创建分页参数
// 基础分页
Page page = Page.build(1, 10); // 第1页,每页10条
// 带排序
Page page = Page.build(1, 10, Order.desc("create_time"));
// 多字段排序
Page page = Page.build(1, 10, Order.desc("create_time"), Order.asc("id"));
// 仅排序,无分页
Page page = Page.build(Order.desc("create_time"));
使用分页
// Pojo 分页
Page<User> page = DB.pojo.selectWrapper(User.class)
.eq(User::getStatus, 1)
.page(Page.build(1, 10))
.queryBeanPage();
List<User> records = page.getRecords();
long total = page.getTotal();
// Jdbc 分页
Page<ResultMap> page = DB.jdbc.selectWrapper("SELECT * FROM user WHERE status = ?", 1)
.page(Page.build(1, 10, Order.desc("create_time")))
.queryPage();
排序
// 不分页排序
List<User> users = DB.pojo.selectWrapper(User.class)
.orderByDesc(User::getCreateTime)
.orderByAsc(User::getId)
.queryBeanList();
// Order 构造
Order.asc("field") // 升序
Order.desc("field") // 降序
Order.ascs("a", "b") // 多字段升序
Order.descs("a", "b") // 多字段降序
分页结果
| 方法 | 返回类型 | 说明 |
|---|---|---|
getRecords() | List<T> | 当前页数据 |
getTotal() | long | 总条数 |
getPages() | long | 总页数 |
getCurrent() | long | 当前页码 |
getSize() | long | 每页条数 |
hasNext() | boolean | 是否有下一页 |
hasPrevious() | boolean | 是否有上一页 |
pageNo()、pageSize() 和 pages() 提供 int 形式的简洁访问器。当前单页大小上限为 5000。
Bean 映射
查询列会自动按常见命名规则映射到 Bean 属性:
| 数据库字段 | Bean 属性 | 说明 |
|---|---|---|
user_name | userName | 下划线转驼峰 |
USER_NAME | userName | 大写下划线转驼峰 |
username | username | 直接匹配 |
@TableName("sys_user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
@TableField("user_name")
private String userName;
private Integer deleted;
private Date createTime;
}
常用注解:
| 注解 | 作用 |
|---|---|
@TableName | 指定表名 |
@TableField | 指定字段名以及字段是否参与映射 |
@TableId | 指定主键字段和生成策略 |
框架可将名为 id 的字段识别为主键,但不会因此推断数据库自增策略。需要自增回填时应显式使用 @TableId(type = IdType.AUTO);@TableId 的默认策略是 IdType.SEQ。
ResultMap
不需要实体类时可以直接返回 ResultMap:
ResultMap result = DB.table.selectWrapper("user")
.eq("id", id)
.queryOne();
String name = result.getStr("name");
Integer age = result.getInt("age", 0);
Long userId = result.getLong("id");
Date createTime = result.getDate("create_time");
ResultMap 还支持 JSON 路径取值:
String city = result.getStr("profile.address.city", "未知");
List<Order> orders = result.getList("orders", Order.class);
String lastTag = result.getStr("tags[-1]");
查询返回类型
| 方法 | 返回 | 语义 |
|---|---|---|
queryBean() | T / null | 严格单条 Bean,多条抛异常 |
queryFirstBean() | T / null | 非严格取第一条 Bean |
queryOne() | ResultMap / null | 严格单条 Map,多条抛异常 |
queryFirst() | ResultMap / null | 非严格取第一条 Map |
queryBeanList() | List<T> | Bean 列表 |
queryList() | List<ResultMap> | Map 列表 |
queryOne(Class) | 指定类型 / null | 严格单条指定类型 |
queryFirst(Class) | 指定类型 / null | 非严格取第一条指定类型 |
queryList(Class) | List<T> | 指定类型列表 |
queryBeanPage() | Page<T> | Bean 分页 |
queryPage() | Page<ResultMap> | Map 分页 |
queryStr/Int/Long/Double() | 对应标量 | 单列单值 |
count() | long | 数量 |
queryFirst* 应配合显式排序使用,否则数据库不保证“第一条”的稳定顺序。
原生 JDBC 分页边界
DB.jdbc.page(sql, PageRequest.of(...), ...) 和 JDBC Wrapper 会自动改写 count SQL。当前改写逻辑较为朴素,复杂 GROUP BY、DISTINCT、UNION 查询应使用验证过的独立统计 SQL 或预设 SQL,不要假定自动改写始终正确。