SQL 映射 XML 文件是 MyBatis 中所有 SQL 語句的定義場所。本文系統講解 resultMap、CRUD 標籤、sql 片段復用、參數傳遞、緩存配置等核心內容,並通過「學生-班級-教師」關聯模型演示一對一、一對多映射及鑑別器用法。
resultMap 是 MyBatis 最強大的元素,能減少 90% 的 JDBC 結果集手動映射代碼,支持複雜關聯對象的自動裝配。
| 屬性 | 說明 |
|---|---|
| type | Java 實體類全限定名或別名 |
| id | resultMap 唯一標識 |
主要子元素:
constructor:通過構造函數注入屬性值id:主鍵字段映射,標識結果對象唯一性result:普通字段映射到 JavaBean 屬性association:一對一關聯對象映射collection:一對多集合映射discriminator:根據字段值動態選擇 resultMap(類似 switch)<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(自定義類型處理器)。
適用於不可變對象或無 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) { ... }
場景:班級 ClassEntity 包含班主任 TeacherEntity。
<!-- 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 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>
場景:班級包含多名學生 List<StudentEntity> studentList。
<collection property="studentList" column="CLASS_ID" javaType="ArrayList" ofType="StudentEntity" select="getStudentByClassID"/>
對應 StudentMapper 中需提供按班級 ID 查詢學生的 select 語句。
<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>
根據某字段值(如 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>
<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。
支持數據庫自增主鍵(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>
屬性與 select 類似,無 resultType/resultMap。
<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>
#{paramName}。#{propertyName} 訪問屬性或鍵值。@Param("name"),SQL 中用 #{name} 引用。<where>、<if> 實現靈活查詢。二級緩存默認關閉,開啟只需在映射文件添加 <cache/>。屬性:eviction(回收策略 LRU/FIFO/SOFT/WEAK)、flushInterval(刷新間隔毫秒)、size(引用數量)、readOnly(只讀/可讀寫)。跨命名空間共享緩存用 <cache-ref namespace="..."/>。
MyBatis SQL 映射文件提供了極其靈活的結果映射、動態 SQL、緩存控制能力。掌握 resultMap 的關聯映射(association/collection)、鑑別器、構造函數注入等進階用法,能優雅解決複雜對象圖的持久化問題;合理使用 sql 片段復用與參數綁定,可大幅提升代碼可維護性;二級緩存配置得當能顯著提升查詢性能。