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

MyBatis CRUD 與分頁查詢最佳實踐指南

     編輯:Java 相關知識

MyBatis 核心優勢回顧

MyBatis 作為半自動 ORM 框架,將 SQL 寫在 XML 或註解中,保留了對 SQL 的完全控制權,適合複雜查詢、性能敏感場景。本文聚焦:通用 CRUD 封裝、分頁插件集成、動態 SQL 技巧、性能優化要點。

基礎 CRUD 映射規範

實體類與結果映射

<resultMap id="userMap" type="com.example.User">
    <id property="id" column="user_id"/>
    <result property="username" column="user_name"/>
    <result property="email" column="email"/>
    <result property="createdAt" column="created_at"/>
</resultMap>

通用增刪改查模板

<!-- 插入 -->
<insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO sys_user(user_name, email, created_at)
    VALUES(#{username}, #{email}, NOW())
</insert>

<!-- 刪除 -->
<delete id="deleteById">
    DELETE FROM sys_user WHERE user_id = #{id}
</delete>

<!-- 更新 -->
<update id="update">
    UPDATE sys_user 
    SET user_name = #{username}, email = #{email}
    WHERE user_id = #{id}
</update>

<!-- 單查 -->
<select id="selectById" resultMap="userMap">
    SELECT user_id, user_name, email, created_at FROM sys_user WHERE user_id = #{id}
</select>

<!-- 列表查詢 -->
<select id="selectList" resultMap="userMap">
    SELECT user_id, user_name, email, created_at FROM sys_user
    <where>
        <if test="username != null">AND user_name LIKE CONCAT('%', #{username}, '%')</if>
        <if test="email != null">AND email = #{email}</if>
    </where>
    ORDER BY created_at DESC
</select>

分頁查詢方案對比

方案一:物理分頁(推薦) - PageHelper 插件

引入依賴:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
</dependency>

配置 application.yml:

pagehelper:
  helper-dialect: mysql
  reasonable: true
  support-methods-arguments: true
  params: count=countSql

使用極簡:

PageHelper.startPage(pageNum, pageSize);
List<User> list = userMapper.selectList(param);
PageInfo<User> pageInfo = new PageInfo<>(list);
// pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList()

原理:攔截 Executor.query,根據數據庫方言自動改寫 SQL 追加 LIMIT/OFFSET(MySQL)、ROWNUM(Oracle)、OFFSET FETCH(PostgreSQL/SQL Server 2012+)。

方案二:邏輯分頁(不推薦大數據量)

一次性查全量再內存分頁,僅適用於極小數據集(< 1000 行)。

方案三:手寫 Count + Limit SQL(無插件環境)

<select id="selectPage" resultMap="userMap">
    SELECT * FROM sys_user
    <where>...</where>
    ORDER BY created_at DESC
    LIMIT #{offset}, #{pageSize}
</select>
<select id="selectCount" resultType="long">
    SELECT COUNT(1) FROM sys_user <where>...</where>
</select>

Service 層手動組裝 PageResult。缺點:代碼侵入性強、維護成本高、易出錯。

動態 SQL 進階技巧

  • <where> 智能去除首個 AND/OR
  • <trim prefix="WHERE" prefixOverrides="AND |OR"> 更靈活的條件拼接
  • <foreach collection="ids" item="id" separator=",">#{id}</foreach> 實現 IN 列表
  • <bind name="pattern" value="'%' + username + '%'" /> 變量預綁定簡化 LIKE
  • <choose><when><otherwise> 互斥條件分支

性能優化清單

  1. 避免 SELECT *:顯式列出列名,減少網絡傳輸、利用覆蓋索引。
  2. 合理使用 resultMap:複雜關聯查詢用 <association>/<collection> 替代多次查詢(N+1 問題)。
  3. 批量操作用 foreach 批量插入:INSERT INTO t(a,b) VALUES <foreach>(#{item.a},#{item.b})</foreach>,單條提交效率極低。
  4. 開啟二級緩存:只讀、高頻、低變更表配置 <cache/>,配合 Ehcache/Redis。
  5. SQL 執行計劃分析:定期 EXPLAIN 核心慢查詢,補充索引。

常見坑與避坑指南

問題原因解決
分頁總數錯誤Count SQL 自動生成失敗(複雜關聯/子查詢)手寫 Count SQL 或配置 countSql
映射報錯列名與屬性名不一致、未配置 resultMap統一使用 resultMap、開啟 mapUnderscoreToCamelCase
批量插入超限MySQL max_allowed_packet / 佔位符超過 65535分批提交、調大參數、改用 LOAD DATA
緩存髒讀二級緩存未正確失效增刪改配置 flushCache="true"、合理設置 eviction

總結

MyBatis 給予 SQL 完全控制權,配合 PageHelper 實現零侵入分頁,動態 XML 構建靈活查詢。遵循「顯式列映射、物理分頁、批量操作、緩存策略」四原則,可構建高性能、易維護的持久層。

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