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

MyBatis 核心特性深度解析:Mapper 接口、ResultMap、別名、SQL 片段與動態 SQL

     編輯:Java 相關知識

前言

MyBatis 作為半自動 ORM 框架,其核心優勢在於 SQL 完全可控與強大的映射能力。本文系統講解五大核心特性:getMapper() 強類型代理、resultMap 複雜結果映射、typeAlias 別名簡化、sql 片段復用、動態 SQL 標籤(where/set/if/choose)。

1. getMapper():強類型 Mapper 代理機制

傳統 session.selectList("namespace.id") 為弱類型(字符串鍵),易拼寫錯誤且無 IDE 支援。getMapper() 通過 JDK 動態代理生成 Mapper 接口實現類,實現強類型調用:

步驟一:定義 Mapper 接口

public interface IDeptDao {
    List<Dept> getAllDept(); // 方法名 = XML 中 select id
}

步驟二:XML 映射文件

<mapper namespace="cn.happy.dao.IDeptDao">
    <select id="getAllDept" resultType="cn.happy.entity.Dept">
        select * from Dept
    </select>
</mapper>

步驟三:強類型調用

IDeptDao mapper = session.getMapper(IDeptDao.class);
List<Dept> list = mapper.getAllDept(); // 編譯期檢查,IDE 跳轉、重構友好

原理

MyBatis 使用 MapperProxyFactory 創建代理類,攔截方法調用 → 解析 MapperMethod → 執行 SqlSession 底層查詢 → 結果映射返回。接口方法名必須與 XML id 完全一致,參數類型需匹配 parameterType。

2. resultMap:解決實體屬性與數據庫字段不匹配

當實體類屬性名與表字段名不一致(如駝峰 vs 下劃線),或需關聯查詢(一對一、一對多)時,必須使用 resultMap:

關聯查詢示例:員工 + 所屬部門

<resultMap type="cn.resultMap.entity.Emp" id="empMap">
    <id property="empId" column="EMPID"/>
    <result property="empName" column="EMPNAME"/>
    <result property="empCity" column="EMPCITY"/>
    <!-- 多方實體嵌入一方:使用 association -->
    <association property="dept" javaType="cn.resultMap.entity.Dept">
        <result property="deptName" column="DEPTNAME"/>
        <result property="deptNo" column="DEPTNO"/>
    </association>
</resultMap>

<select id="getAllEmps" resultMap="empMap">
    select e.*, d.* from Emp e, Dept d where e.deptNo = d.deptNo
</select>
  • id:標識主鍵列,對比優化(緩存、嵌套結果去重)。
  • association:一對一關聯(多方持有一方引用)。
  • collection:一對多關聯(一方持有多方列表),ofType 指定泛型類型。

3. SQL 片段:消除重複 SQL 片段

<sql id="deptColumns"> d.deptNo, d.deptName </sql>

<select id="getAllEmps" resultMap="empMap">
    select e.*, <include refid="deptColumns"/> 
    from Emp e, Dept d where e.deptNo = d.deptNo
</select>

<sql> 定義可復用片段,<include refid="..."/> 引入。支援參數化:<sql id="cols"> ${columns} </sql>。

4. 類型別名:簡化全限定類名

全局配置 (mybatis-config.xml)

<typeAliases>
    <typeAlias type="cn.resultMap.entity.Emp" alias="emp"/>
    <!-- 批量掃描包下所有類,別名默認為類名首字母小寫 -->
    <package name="cn.resultMap.entity"/>
</typeAliases>

映射文件中使用

<select id="getAllEmps" resultMap="empMap" resultType="emp"> ... </select>

內建別名:_byte, _short, _int, _long, _float, _double, _boolean, string, map, list, array 等。

5. 動態 SQL:構建靈活查詢與更新

核心標籤:if、choose/when/otherwise、where、set、trim、foreach、bind。

動態查詢:多條件搜尋員工

<select id="testAllEmpBySelect" parameterType="emp" resultType="emp">
    select * from Emp
    <where>
        <if test="empId != null"> and empId = #{empId} </if>
        <if test="empName != null and empName != ''"> and empName = #{empName} </if>
        <if test="empCity != null"> and empCity = #{empCity} </if>
    </where>
</select>

<where> 智能處理:若內容為空則不輸出 WHERE;若以 AND/OR 開頭則自動去除首個關鍵字。

動態更新:部門信息部分更新

<update id="testUpdate" parameterType="dept">
    update dept
    <set>
        <if test="deptNo != null"> deptNo = #{deptNo}, </if>
        <if test="deptName != null"> deptName = #{deptName}, </if>
    </set>
    where deptNo = #{deptNo}
</update>

<set> 智能處理:若內容為空則不輸出 SET;自動去除末尾逗號。

choose/when/otherwise:互斥條件分支

<select id="search" resultType="emp">
    select * from Emp
    <where>
        <choose>
            <when test="id != null"> empId = #{id} </when>
            <when test="name != null"> empName like #{name} </when>
            <otherwise> 1=1 </otherwise>
        </choose>
    </where>
</select>

測試代碼片段

// 動態查詢測試
Emp emp = new Emp();
emp.setEmpCity("sh");
List<Emp> list = session.selectList("cn.resultMap.dao.IEmpDao.testAllEmpBySelect", emp);

// 動態更新測試
Dept dept = new Dept();
dept.setDeptNo(1);
dept.setDeptName("財政部");
int rows = session.update("cn.resultMap.dao.IDeptDao.testUpdate", dept);
session.commit();

最佳實踐總結

  1. 優先使用 getMapper():類型安全、重構友好、減少字符串錯誤。
  2. 複雜映射必用 resultMap:resultType 僅適用於字段名與屬性名完全一致的簡單場景。
  3. 抽取公共列為 <sql>:減少維護成本,保證一致性。
  4. 全局配置 typeAliases 掃描包:避免逐個手工註冊。
  5. 動態 SQL 善用 where/set/trim:避免手動拼接 SQL 導致的語法錯誤與注入風險。
  6. #{} 預編譯參數 vs ${} 字符串替換:默認用 #{} 防注入;${} 僅用於表名、列名、排序字段等不可預編譯場景。

總結

掌握這五大核心特性,即可駕馭 MyBatis 90% 以上的實戰場景:從簡單 CRUD 到複雜多表關聯、動態報表查詢、批量操作。關鍵在於理解「SQL 與對象映射的分離」與「動態構建 SQL 的聲明式邏輯」。

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