首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MyBatis 手動實現物理分頁完整教程:從原理到代碼落地

     編輯:Java 綜合教學

分頁基礎知識

類型原理優點缺點
物理分頁SQL 層面僅查詢當前頁數據(LIMIT/ROWNUM/TOP)內存佔用極低,適合大數據量需資料庫支援,跨資料庫需適配
邏輯分頁一次性查全表載入內存,再在記憶體切頁查詢簡單,後續翻頁極快內存壓力大,不適合大數據

生產環境 強烈推薦物理分頁。

主流資料庫分頁語法

-- MySQL / PostgreSQL / SQLite
SELECT * FROM t LIMIT offset, pageSize;

-- SQL Server 2012+
SELECT * FROM t ORDER BY id OFFSET offset ROWS FETCH NEXT pageSize ROWS ONLY;

-- Oracle 12c+
SELECT * FROM t OFFSET offset ROWS FETCH NEXT pageSize ROWS ONLY;
-- Oracle 11g 經典寫法
SELECT * FROM (SELECT a.*, ROWNUM rn FROM (SELECT * FROM t) a WHERE ROWNUM <= offset+pageSize) WHERE rn > offset;

MyBatis 手動分頁實戰(以 MySQL 為例)

1. 實體類

public class User {
    private Long id;
    private String username;
    private String email;
    // getter/setter 省略
}

2. Mapper XML

<mapper namespace="com.example.dao.UserMapper">
    <!-- 物理分頁查詢:#{page.start} 對應 Page 物件的 start 屬性 -->
    <select id="selectPage" resultType="com.example.entity.User">
        SELECT id, username, email
        FROM sys_user
        <where>
            <if test="param.keyword != null and param.keyword != ''">
                AND username LIKE CONCAT('%', #{param.keyword}, '%')
            </if>
        </where>
        ORDER BY id DESC
        LIMIT #{page.start}, #{page.pageSize}
    </select>

    <!-- 總條數查詢(不分頁) -->
    <select id="selectCount" resultType="long">
        SELECT COUNT(1) FROM sys_user
        <where>
            <if test="keyword != null and keyword != ''">
                AND username LIKE CONCAT('%', #{keyword}, '%')
            </if>
        </where>
    </select>
</mapper>

3. 分頁工具類

public class Page<T> implements Serializable {
    private int pageNum = 1;       // 當前頁(1-based)
    private int pageSize = 10;     // 每頁條數
    private long total;            // 總條數
    private List<T> records;       // 當前頁數據

    // 計算屬性
    public int getStart() { return (pageNum - 1) * pageSize; }
    public long getPages() { return (total + pageSize - 1) / pageSize; }
    public boolean hasPrevious() { return pageNum > 1; }
    public boolean hasNext() { return pageNum < getPages(); }
    // getter/setter 省略
}

4. Service 層組裝

@Service
public class UserServiceImpl implements UserService {
    @Autowired UserMapper userMapper;

    @Override
    public Page<User> queryPage(int pageNum, int pageSize, String keyword) {
        Page<User> page = new Page<>();
        page.setPageNum(pageNum);
        page.setPageSize(pageSize);

        // 1. 查總數
        long total = userMapper.selectCount(keyword);
        page.setTotal(total);

        // 2. 查當前頁數據
        Map<String, Object> param = new HashMap<>();
        param.put("page", page);
        param.put("keyword", keyword);
        List<User> records = userMapper.selectPage(param);
        page.setRecords(records);

        return page;
    }
}

5. Controller 返回 JSON

@GetMapping("/users")
public Result<Page<User>> list(
        @RequestParam(defaultValue = "1") int pageNum,
        @RequestParam(defaultValue = "10") int pageSize,
        @RequestParam(required = false) String keyword) {
    return Result.ok(userService.queryPage(pageNum, pageSize, keyword));
}

進階提示:分頁插件對比

插件特點適用場景
PageHelper無侵入、支援多種 DB、自動攔截 RowBounds快速接入舊專案、團隊熟悉 MyBatis
MyBatis-Plus內建 IPage、條件構造器、代碼生成器新專案、追求開發效率
手寫完全可控、零依賴、適合學習原理特殊分頁邏輯、極簡依賴要求

總結

手寫物理分頁核心在於 「總數查詢 + LIMIT 查詢」 兩條 SQL,配合 Page 物件封裝 start/pageSize。理解此原理後,無論使用 PageHelper 還是 MyBatis-Plus,遇到複雜分頁(如多表關聯、動態排序)也能游刃有餘地定製 SQL。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved