or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

active-record.mdannotations.mdcode-generation.mdcore-crud.mdindex.mdpagination.mdplugins.mdquery-building.mdservice-layer.mdspring-boot.md

pagination.mddocs/

0

# Pagination

1

2

MyBatis-Plus provides comprehensive pagination support with automatic count queries, flexible page configuration, and seamless integration with query wrappers for efficient large dataset handling.

3

4

## Capabilities

5

6

### IPage Interface

7

8

Core pagination interface defining page structure and navigation methods.

9

10

```java { .api }

11

/**

12

* Pagination interface

13

* @param <T> Record type

14

*/

15

public interface IPage<T> extends Serializable {

16

17

/**

18

* Get current page records

19

*/

20

List<T> getRecords();

21

22

/**

23

* Set current page records

24

*/

25

IPage<T> setRecords(List<T> records);

26

27

/**

28

* Get total record count

29

*/

30

long getTotal();

31

32

/**

33

* Set total record count

34

*/

35

IPage<T> setTotal(long total);

36

37

/**

38

* Get page size

39

*/

40

long getSize();

41

42

/**

43

* Set page size

44

*/

45

IPage<T> setSize(long size);

46

47

/**

48

* Get current page number (1-based)

49

*/

50

long getCurrent();

51

52

/**

53

* Set current page number

54

*/

55

IPage<T> setCurrent(long current);

56

57

/**

58

* Get total page count

59

*/

60

default long getPages() {

61

if (getSize() == 0) {

62

return 0L;

63

}

64

long pages = getTotal() / getSize();

65

if (getTotal() % getSize() != 0) {

66

pages++;

67

}

68

return pages;

69

}

70

71

/**

72

* Check if has next page

73

*/

74

default boolean hasNext() {

75

return getCurrent() < getPages();

76

}

77

78

/**

79

* Check if has previous page

80

*/

81

default boolean hasPrevious() {

82

return getCurrent() > 1;

83

}

84

85

/**

86

* Get orders for sorting

87

*/

88

default List<OrderItem> orders() {

89

return new ArrayList<>();

90

}

91

92

/**

93

* Whether to optimize count query

94

*/

95

default boolean optimizeCountSql() {

96

return true;

97

}

98

99

/**

100

* Whether to search count (perform count query)

101

*/

102

default boolean searchCount() {

103

return true;

104

}

105

106

/**

107

* Get count ID for optimization

108

*/

109

default String countId() {

110

return null;

111

}

112

113

/**

114

* Get max limit for single query

115

*/

116

default Long maxLimit() {

117

return null;

118

}

119

}

120

```

121

122

### Page Class

123

124

Default pagination implementation with builder support and order configuration.

125

126

```java { .api }

127

/**

128

* Default pagination implementation

129

* @param <T> Record type

130

*/

131

public class Page<T> implements IPage<T> {

132

133

/**

134

* Default constructor

135

*/

136

public Page();

137

138

/**

139

* Constructor with current page and page size

140

* @param current Current page number (1-based)

141

* @param size Page size

142

*/

143

public Page(long current, long size);

144

145

/**

146

* Constructor with current page, page size, and total

147

* @param current Current page number

148

* @param size Page size

149

* @param total Total record count

150

*/

151

public Page(long current, long size, long total);

152

153

/**

154

* Constructor with search count control

155

* @param current Current page number

156

* @param size Page size

157

* @param searchCount Whether to perform count query

158

*/

159

public Page(long current, long size, boolean searchCount);

160

161

/**

162

* Constructor with all parameters

163

* @param current Current page number

164

* @param size Page size

165

* @param total Total record count

166

* @param searchCount Whether to perform count query

167

*/

168

public Page(long current, long size, long total, boolean searchCount);

169

170

/**

171

* Add order item for sorting

172

* @param orderItem Order configuration

173

*/

174

public Page<T> addOrder(OrderItem orderItem);

175

176

/**

177

* Add multiple order items

178

* @param orderItems Order configurations

179

*/

180

public Page<T> addOrder(List<OrderItem> orderItems);

181

182

/**

183

* Set orders (replaces existing)

184

* @param orders New order configurations

185

*/

186

public Page<T> setOrders(List<OrderItem> orders);

187

188

/**

189

* Set whether to optimize count SQL

190

* @param optimizeCountSql Optimization flag

191

*/

192

public Page<T> setOptimizeCountSql(boolean optimizeCountSql);

193

194

/**

195

* Set whether to search count

196

* @param searchCount Search count flag

197

*/

198

public Page<T> setSearchCount(boolean searchCount);

199

200

/**

201

* Set count ID for optimization

202

* @param countId Count ID

203

*/

204

public Page<T> setCountId(String countId);

205

206

/**

207

* Set max limit for single query

208

* @param maxLimit Max limit

209

*/

210

public Page<T> setMaxLimit(Long maxLimit);

211

}

212

```

213

214

### OrderItem Class

215

216

Sorting configuration for pagination queries.

217

218

```java { .api }

219

/**

220

* Order item for sorting configuration

221

*/

222

public class OrderItem implements Serializable {

223

224

/**

225

* Column name for sorting

226

*/

227

private String column;

228

229

/**

230

* Whether ascending (true) or descending (false)

231

*/

232

private boolean asc = true;

233

234

/**

235

* Constructor

236

*/

237

public OrderItem();

238

239

/**

240

* Constructor with column and direction

241

* @param column Column name

242

* @param asc Sort direction (true for ASC, false for DESC)

243

*/

244

public OrderItem(String column, boolean asc);

245

246

/**

247

* Static factory method for ascending order

248

* @param column Column name

249

* @return OrderItem for ascending sort

250

*/

251

public static OrderItem asc(String column);

252

253

/**

254

* Static factory method for descending order

255

* @param column Column name

256

* @return OrderItem for descending sort

257

*/

258

public static OrderItem desc(String column);

259

260

/**

261

* Static factory method for multiple ascending orders

262

* @param columns Column names

263

* @return List of OrderItems for ascending sorts

264

*/

265

public static List<OrderItem> ascs(String... columns);

266

267

/**

268

* Static factory method for multiple descending orders

269

* @param columns Column names

270

* @return List of OrderItems for descending sorts

271

*/

272

public static List<OrderItem> descs(String... columns);

273

274

// getters and setters...

275

}

276

```

277

278

## Usage Examples

279

280

**Basic Pagination:**

281

282

```java

283

// Simple pagination

284

Page<User> page = new Page<>(1, 10); // Page 1, 10 records per page

285

IPage<User> result = userService.page(page);

286

287

System.out.println("Total records: " + result.getTotal());

288

System.out.println("Total pages: " + result.getPages());

289

System.out.println("Current page: " + result.getCurrent());

290

System.out.println("Page size: " + result.getSize());

291

System.out.println("Records: " + result.getRecords().size());

292

System.out.println("Has next: " + result.hasNext());

293

System.out.println("Has previous: " + result.hasPrevious());

294

```

295

296

**Pagination with Query Conditions:**

297

298

```java

299

// Pagination with conditions

300

Page<User> page = new Page<>(1, 10);

301

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

302

wrapper.eq(User::getStatus, 1)

303

.like(User::getName, "John")

304

.orderByDesc(User::getCreateTime);

305

306

IPage<User> result = userService.page(page, wrapper);

307

308

// Or using mapper directly

309

IPage<User> result = userMapper.selectPage(page, wrapper);

310

```

311

312

**Pagination with Sorting:**

313

314

```java

315

// Using OrderItem for sorting

316

Page<User> page = new Page<>(1, 10);

317

page.addOrder(OrderItem.desc("create_time"))

318

.addOrder(OrderItem.asc("name"));

319

320

IPage<User> result = userService.page(page);

321

322

// Multiple orders at once

323

List<OrderItem> orders = Arrays.asList(

324

OrderItem.desc("create_time"),

325

OrderItem.asc("name"),

326

OrderItem.desc("id")

327

);

328

page.setOrders(orders);

329

330

// Factory methods for convenience

331

page.addOrder(OrderItem.descs("create_time", "update_time"))

332

.addOrder(OrderItem.ascs("name", "email"));

333

```

334

335

**Performance Optimization:**

336

337

```java

338

// Disable count query for better performance (when total not needed)

339

Page<User> page = new Page<>(1, 10, false); // searchCount = false

340

IPage<User> result = userService.page(page);

341

// result.getTotal() will be 0, but records are fetched normally

342

343

// Optimize count SQL

344

Page<User> page = new Page<>(1, 10);

345

page.setOptimizeCountSql(true); // Default is true

346

IPage<User> result = userService.page(page);

347

348

// Set count ID for complex queries

349

page.setCountId("customCountQuery");

350

351

// Set max limit to prevent large queries

352

page.setMaxLimit(1000L);

353

```

354

355

**Custom Pagination Queries:**

356

357

```java

358

// Custom mapper method with pagination

359

@Mapper

360

public interface UserMapper extends BaseMapper<User> {

361

362

@Select("SELECT u.*, d.name as dept_name FROM user u LEFT JOIN department d ON u.dept_id = d.id WHERE u.status = #{status}")

363

IPage<UserWithDept> selectUsersWithDept(IPage<UserWithDept> page, @Param("status") Integer status);

364

365

// XML-based custom query

366

IPage<User> selectActiveUsers(IPage<User> page, @Param("minAge") Integer minAge);

367

}

368

369

// Usage

370

Page<UserWithDept> page = new Page<>(1, 10);

371

IPage<UserWithDept> result = userMapper.selectUsersWithDept(page, 1);

372

373

Page<User> page = new Page<>(1, 10);

374

IPage<User> result = userMapper.selectActiveUsers(page, 18);

375

```

376

377

**Map-based Pagination:**

378

379

```java

380

// Paginate maps instead of entities

381

Page<Map<String, Object>> page = new Page<>(1, 10);

382

LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

383

wrapper.select(User::getId, User::getName, User::getEmail)

384

.eq(User::getStatus, 1);

385

386

IPage<Map<String, Object>> result = userService.pageMaps(page, wrapper);

387

388

// Or using mapper

389

IPage<Map<String, Object>> result = userMapper.selectMapsPage(page, wrapper);

390

```

391

392

**Service Layer Chain Pagination:**

393

394

```java

395

// Using service chain methods

396

Page<User> page = new Page<>(1, 10);

397

IPage<User> result = userService.lambdaQuery()

398

.eq(User::getStatus, 1)

399

.gt(User::getAge, 18)

400

.orderByDesc(User::getCreateTime)

401

.page(page);

402

```

403

404

**Pagination Helper Utilities:**

405

406

```java

407

// Utility class for common pagination operations

408

public class PageUtils {

409

410

public static <T> Page<T> buildPage(int current, int size) {

411

return new Page<>(current, size);

412

}

413

414

public static <T> Page<T> buildPageWithOrder(int current, int size, String orderBy, boolean asc) {

415

Page<T> page = new Page<>(current, size);

416

page.addOrder(new OrderItem(orderBy, asc));

417

return page;

418

}

419

420

public static <T> PageResult<T> toPageResult(IPage<T> page) {

421

PageResult<T> result = new PageResult<>();

422

result.setRecords(page.getRecords());

423

result.setTotal(page.getTotal());

424

result.setCurrent(page.getCurrent());

425

result.setSize(page.getSize());

426

result.setPages(page.getPages());

427

return result;

428

}

429

}

430

431

// Usage

432

Page<User> page = PageUtils.buildPageWithOrder(1, 10, "create_time", false);

433

IPage<User> result = userService.page(page);

434

PageResult<User> pageResult = PageUtils.toPageResult(result);

435

```

436

437

**Error Handling and Validation:**

438

439

```java

440

// Validate pagination parameters

441

public IPage<User> getUsers(int current, int size) {

442

// Validate parameters

443

if (current < 1) {

444

throw new IllegalArgumentException("Page number must be positive");

445

}

446

if (size < 1 || size > 100) {

447

throw new IllegalArgumentException("Page size must be between 1 and 100");

448

}

449

450

Page<User> page = new Page<>(current, size);

451

return userService.page(page);

452

}

453

454

// Handle pagination edge cases

455

public IPage<User> getUsersSafely(int current, int size) {

456

// Ensure valid parameters

457

current = Math.max(1, current);

458

size = Math.min(Math.max(1, size), 100);

459

460

Page<User> page = new Page<>(current, size);

461

IPage<User> result = userService.page(page);

462

463

// Check if current page exceeds total pages

464

if (result.getCurrent() > result.getPages() && result.getPages() > 0) {

465

// Redirect to last page

466

page.setCurrent(result.getPages());

467

result = userService.page(page);

468

}

469

470

return result;

471

}

472

```

473

474

**Performance Considerations:**

475

476

- Use `searchCount = false` when total count is not needed

477

- Optimize count queries by setting `optimizeCountSql = true`

478

- Set reasonable max limits to prevent large queries

479

- Use appropriate indexes for ORDER BY columns

480

- Consider using cursor-based pagination for very large datasets

481

- Cache count results for frequently accessed data