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

深度解析 MyBatis SQL 映射文件編寫詳解

     編輯:Java 相關知識

概述

SQL 映射 XML 文件是 MyBatis 中所有 SQL 語句的定義場所。本文系統講解 resultMap、CRUD 標籤、sql 片段復用、參數傳遞、緩存配置等核心內容,並通過「學生-班級-教師」關聯模型演示一對一、一對多映射及鑑別器用法。

1. resultMap 結果映射詳解

resultMap 是 MyBatis 最強大的元素,能減少 90% 的 JDBC 結果集手動映射代碼,支持複雜關聯對象的自動裝配。

1.1 基礎屬性與子元素

屬性說明
typeJava 實體類全限定名或別名
idresultMap 唯一標識

主要子元素:

  • constructor:通過構造函數注入屬性值
  • id:主鍵字段映射,標識結果對象唯一性
  • result:普通字段映射到 JavaBean 屬性
  • association:一對一關聯對象映射
  • collection:一對多集合映射
  • discriminator:根據字段值動態選擇 resultMap(類似 switch)

1.2 id / result 簡單映射示例

<resultMap type="StudentEntity" id="studentResultMap">
    <id property="studentId" column="STUDENT_ID" javaType="String" jdbcType="VARCHAR"/>
    <result property="studentName" column="STUDENT_NAME" javaType="String" jdbcType="VARCHAR"/>
    <result property="studentSex" column="STUDENT_SEX" javaType="int" jdbcType="INTEGER"/>
    <result property="studentBirthday" column="STUDENT_BIRTHDAY" javaType="Date" jdbcType="DATE"/>
    <result property="studentPhoto" column="STUDENT_PHOTO" javaType="byte[]" jdbcType="BLOB" typeHandler="org.apache.ibatis.type.BlobTypeHandler" />
</resultMap>

屬性詳解:property(實體屬性)、column(數據庫列名)、javaType(Java 類型)、jdbcType(JDBC 類型,針對可空列插入更新時必需)、typeHandler(自定義類型處理器)。

1.3 constructor 構造函數映射

適用於不可變對象或無 setter 的場景,按構造函數參數順序映射。

<resultMap type="StudentEntity" id="studentResultMap">
    <constructor>
        <idArg javaType="String" column="STUDENT_ID"/>
        <arg javaType="String" column="STUDENT_NAME"/>
        <arg javaType="String" column="STUDENT_SEX"/>
        <arg javaType="Date" column="STUDENT_BIRTHDAY"/>
    </constructor>
</resultMap>

需實體類提供對應構造函數:

public StudentEntity(String studentID, String studentName, String studentSex, Date studentBirthday) { ... }

1.4 association 一對一關聯映射

場景:班級 ClassEntity 包含班主任 TeacherEntity。

方式一:select 獨立查詢(靈活、支持延遲加載)

<!-- ClassMapper.xml -->
<resultMap type="ClassEntity" id="classResultMap">
    <id property="classID" column="CLASS_ID" />
    <result property="className" column="CLASS_NAME" />
    <result property="classYear" column="CLASS_YEAR" />
    <association property="teacherEntity" column="TEACHER_ID" select="getTeacher"/>
</resultMap>
<select id="getClassByID" parameterType="String" resultMap="classResultMap">
    SELECT * FROM CLASS_TBL CT WHERE CT.CLASS_ID = #{classID};
</select>

<!-- TeacherMapper.xml -->
<select id="getTeacher" parameterType="String" resultMap="teacherResultMap">
    SELECT * FROM TEACHER_TBL TT WHERE TT.TEACHER_ID = #{teacherID}
</select>

方式二:resultMap 嵌套結果映射(JOIN 查詢,性能更優)

<resultMap type="ClassEntity" id="classResultMap">
    <id property="classID" column="CLASS_ID" />
    <result property="className" column="CLASS_NAME" />
    <result property="classYear" column="CLASS_YEAR" />
    <association property="teacherEntity" column="TEACHER_ID" resultMap="teacherResultMap"/>
</resultMap>
<select id="getClassAndTeacher" parameterType="String" resultMap="classResultMap">
    SELECT * FROM CLASS_TBL CT LEFT JOIN TEACHER_TBL TT ON CT.TEACHER_ID = TT.TEACHER_ID WHERE CT.CLASS_ID = #{classID};
</select>

1.5 collection 一對多集合映射

場景:班級包含多名學生 List<StudentEntity> studentList。

方式一:select 獨立查詢

<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" select="getStudentByClassID"/>

對應 StudentMapper 中需提供按班級 ID 查詢學生的 select 語句。

方式二:resultMap 嵌套結果映射(JOIN 查詢)

<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" resultMap="studentResultMap"/>
<select id="getClassAndTeacherStudent" parameterType="String" resultMap="classResultMap">
    SELECT * FROM CLASS_TBL CT
    LEFT JOIN STUDENT_TBL ST ON CT.CLASS_ID = ST.CLASS_ID
    LEFT JOIN TEACHER_TBL TT ON CT.TEACHER_ID = TT.TEACHER_ID
    WHERE CT.CLASS_ID = #{classID};
</select>

1.6 discriminator 鑑別器動態映射

根據某字段值(如 CLASS_ID)決定使用哪個 resultMap,支持繼承結構映射。

<resultMap type="StudentEntity" id="resultMap_studentEntity_discriminator">
    <id property="studentId" column="STUDENT_ID" .../>
    <result property="studentName" column="STUDENT_NAME" .../>
    <discriminator column="CLASS_ID" javaType="String" jdbcType="VARCHAR">
        <case value="20000001" resultType="StudentEntity">
            <result property="classId" column="CLASS_ID" javaType="String" jdbcType="VARCHAR"/>
        </case>
    </discriminator>
</resultMap>

2. CRUD、參數與緩存

2.1 select 查詢

<select id="getStudent" parameterType="String" resultMap="studentResultMap">
    SELECT ST.STUDENT_ID, ST.STUDENT_NAME, ST.STUDENT_SEX, ST.STUDENT_BIRTHDAY, ST.CLASS_ID
    FROM STUDENT_TBL ST WHERE ST.STUDENT_ID = #{studentID}
</select>

關鍵屬性:parameterType(輸入參數類型)、resultType/resultMap(輸出映射,二擇一)、flushCache、useCache、timeout、fetchSize、statementType、resultSetType。

2.2 insert 插入

支持數據庫自增主鍵(useGeneratedKeys="true" keyProperty="id")或 selectKey 自定義主鍵生成策略(如 Oracle 序列、MySQL 函數)。

<insert id="insertStudentAutoKey" parameterType="StudentEntity">
    <selectKey keyProperty="studentID" resultType="String" order="BEFORE">
        select nextval('student')
    </selectKey>
    INSERT INTO STUDENT_TBL (...) VALUES (#{studentID}, #{studentName}, ...)
</insert>

2.3 update / delete 更新刪除

屬性與 select 類似,無 resultType/resultMap。

2.4 sql 片段復用

<sql id="selectStudentAll">
    SELECT ST.STUDENT_ID, ST.STUDENT_NAME, ... FROM STUDENT_TBL ST
</sql>
<select id="getStudent" ...>
    <include refid="selectStudentAll"/> WHERE ST.STUDENT_ID = #{studentID}
</select>

2.5 參數傳遞方式

  • 基本類型:單一參數直接用 #{paramName}。
  • 實體類/Map:通過 #{propertyName} 訪問屬性或鍵值。
  • 多參數 @Param:接口方法參數加 @Param("name"),SQL 中用 #{name} 引用。
  • 動態 SQL 條件構建:結合 <where>、<if> 實現靈活查詢。

2.6 緩存配置

二級緩存默認關閉,開啟只需在映射文件添加 <cache/>。屬性:eviction(回收策略 LRU/FIFO/SOFT/WEAK)、flushInterval(刷新間隔毫秒)、size(引用數量)、readOnly(只讀/可讀寫)。跨命名空間共享緩存用 <cache-ref namespace="..."/>。

總結

MyBatis SQL 映射文件提供了極其靈活的結果映射、動態 SQL、緩存控制能力。掌握 resultMap 的關聯映射(association/collection)、鑑別器、構造函數注入等進階用法,能優雅解決複雜對象圖的持久化問題;合理使用 sql 片段復用與參數綁定,可大幅提升代碼可維護性;二級緩存配置得當能顯著提升查詢性能。

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