MyBatis 若在 <select> 指定 resultType 而非 resultMap,即啟用結果集自動映射。預設開啟,會將結果集中未在 resultMap 定義的欄位,依名稱匹配(忽略大小寫、支援下劃線轉駝峰)自動賦值給目標物件屬性。
核心在 DefaultResultSetHandler:
createAutomaticMappings:取得未映射欄位名單 (rsw.getUnmappedColumnNames),對每個欄位嘗試透過 MetaObject.findProperty 尋找對應屬性(受 mapUnderscoreToCamelCase 影響),有 setter 則建立映射關係並快取。applyAutomaticMappings:遍歷快取的映射,從 ResultSet 取值經 TypeHandler 轉型後 metaObject.setValue 設入物件。全域設定 autoMappingBehavior(setting 標籤):
NONE:關閉自動映射。PARTIAL (預設):僅對非巢狀 resultMap 自動映射。FULL:對所有 resultMap 自動映射。也可在具體 <resultMap> 上用 autoMapping="true|false" 覆蓋全域設定,優先級更高。
指定 resultType 時,MyBatis 內部會建立一個空的 ResultMap (type=指定類別),後續處理完全走 resultMap 流程,因此自動映射機制同樣生效。若關閉全域自動映射,resultType 將無法自動填充屬性。
<resultMap type="com.example.User" id="BaseResult">
<result column="user_name" property="username"/> <!-- 僅手動映射 user_name -->
</resultMap>
<select id="findById" resultMap="BaseResult" parameterType="Long">
select id, name, username user_name, email, mobile from t_user where id=#{id}
</select>
查詢結果中 id, name, email, mobile 雖未在 resultMap 定義,但會自動映射到 User 物件對應屬性(username 走手動映射)。
// XMLStatementBuilder 解析 resultMap/resultType 邏輯 private ListgetStatementResultMaps(String resultMap, Class> resultType, String statementId) { if (resultMap != null) { /* 解析具名 resultMap */ } else if (resultType != null) { ResultMap inline = new ResultMap.Builder(configuration, statementId + "-Inline", resultType, new ArrayList<>(), null).build(); return Collections.singletonList(inline); } return Collections.emptyList(); }