跳到主要内容

05 - 分页排序

5.1 分页查询

创建分页参数

@Test
public void pageAndOrderTest5_1_1() {
// 基础分页
Page page = Page.build(1, 10); // 第1页,每页10条

// 带排序的分页
Page page2 = Page.build(1, 10, Order.desc("create_time"));

// 多字段排序
Page page3 = Page.build(1, 10, Order.desc("create_time"), Order.asc("id"));

// 只排序,无分页
Page page4 = Page.build(Order.desc("create_time"), Order.asc("id"));

// 分页结果
page.getRecords(); // List<User> 当前页数据
page.getTotal(); // long 总条数
page.getPages(); // int 总页数
page.getCurrent(); // int 当前页码
page.getSize(); // int 每页条数
// 链式设置排序字段
page.addOrder(Order.desc("createTime"), Order.asc("id"));

//非常用方法
page.getSortSql(); // 取得排序SQL
page.getOrders() ; // List<Order> 排序字段
}

Wrapper 分页

@Test
public void pageAndOrderTest5_1_2() {
// 分页构造方式1:page单独构建
final Page<?> page = Page.build(1, 10, Order.desc("create_time"));
DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.page(page)
.queryBeanPage();

// 分页构造方式2:分页和排序链式构建
DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.page(1,10)
.orderByAsc(User::getId)
.queryBeanPage();
}

原生 SQL 分页

@Test
public void pageAndOrderTest5_1_3() {
DB.Jdbc.select("SELECT * FROM user WHERE status = ?", 1)
.page(Page.build(1, 10, Order.desc("id")))
.queryPage();

// 生成 SQL:
// select count(1) from user WHERE status = 1 (自动生成count语句)
// SELECT * FROM user WHERE status = 1 LIMIT 0, 10 (COUNT>0 时才执行)
}

预设 SQL 分页

@Test
public void pageAndOrderTest5_1_4() {
//方法1:预设模版
/**
<sql sqlId="key.pageAndOrderTest5_1_4"><![CDATA[
SELECT * FROM user WHERE and status = #{status}
]]></sql>
*/
DB.Sql.select("key.pageAndOrderTest5_1_4")
.addPara("status", 1)
.page(Page.build(1, 10, Order.desc("id")))
.queryPage();

//方法2:直接写SQL
DB.Sql.select("SELECT * FROM user WHERE and status = #{status}")
.addPara("status", 1)
.page(Page.build(1, 10, Order.desc("id")))
.queryPage();

// 生成 SQL:
// select count(1) from user WHERE status = 1 (自动生成count语句)
// SELECT * FROM user WHERE and status = 1 order by ID desc LIMIT 0,10 (COUNT>0 时才执行)
}

仅排序不分页

@Test
public void pageAndOrderTest5_1_5() {
// 只需要排序,不需要分页
//方法1:设置只有排序的分页
DB.Pojo.select(User.class)
.page(Page.build(Order.descs("create_time", "id"))) // 不传页码
.queryBeanList();
//方法2:直接链式设置order
DB.Pojo.select(User.class)
.orderByDesc("create_time", "id") // 不传页码
.queryBeanList();

// 生成 SQL:
// select * from USER t where IS_DELETED = 0 order by create_time desc,ID desc
// (无 LIMIT)
}

5.2 排序

创建排序对象

@Test
public void pageAndOrderTest5_2_1() {
// 单字段升序
Order.asc("create_time");

// 单字段降序
Order.desc("create_time");

// 多字段升序
Order.ascs("status", "create_time");

// 多字段降序
Order.descs("create_time", "id");

// page 构造
Page.build(1, 10, Order.desc("create_time"), Order.asc("id"));
}

Wrapper 排序

DB.Pojo.select(User.class)
.eq(User::getStatus, 1)
.orderByAsc(User::getLevel)
.orderByDesc(User::getCreateTime)
.queryBeanList();

// 生成 SQL:
// ... ORDER BY level ASC, create_time DESC

动态排序

String sortField = request.getParameter("sort"); // 如 "create_time"
String sortOrder = request.getParameter("order"); // 如 "desc"

Order order = "desc".equals(sortOrder)
? Order.desc(sortField)
: Order.asc(sortField);

DB.Pojo.select(User.class)
.page(Page.build(1, 10, order))
.queryBeanPage();

安全排序(白名单)

// 防止 SQL 注入,只允许特定字段排序
Set<String> allowedFields = Set.of("id", "name", "create_time", "update_time");

String sortField = request.getParameter("sort");
if (!allowedFields.contains(sortField)) {
sortField = "create_time"; // 默认排序字段
}

Order order = Order.desc(sortField);

多字段排序

// 方式1:Order 对象
Page page = Page.build(1, 10,
Order.desc("status"),
Order.desc("create_time"),
Order.asc("id")
);

// 方式2:Wrapper 链式
DB.Pojo.select(User.class)
.orderByDesc(User::getStatus)
.orderByDesc(User::getCreateTime)
.orderByAsc(User::getId)
.queryBeanList();

// 生成 SQL:
// ORDER BY status DESC, create_time DESC, id ASC

NULL 值排序

// 自定义 SQL 处理 NULL 排序
DB.Pojo.select(User.class)
.orderBySql("IFNULL(sort_num, 999999) ASC")
.orderByDesc(User::getCreateTime)
.queryBeanList();