前言
MyBatis是基于“資料庫結構不可控”的思想建立的,也就是我們希望資料庫遵循第三範式或BCNF,但實際事與願違,那麼結果集映射就是MyBatis為我們提供這種理想與現實間轉換的手段了,而resultMap就是結果集映射的配置标簽了。
在深入ResultMap标簽前,我們需要了解從SQL查詢結果集到JavaBean或POJO實體的過程。
從SQL查詢結果到領域模型實體
通過JDBC查詢得到ResultSet對象
周遊ResultSet對象并将每行資料暫存到HashMap執行個體中,以結果集的字段名或字段别名為鍵,以字段值為值
根據ResultMap标簽的type屬性通過反射執行個體化領域模型
根據ResultMap标簽的type屬性和id、result等标簽資訊将HashMap中的鍵值對,填充到領域模型執行個體中并傳回
1、屬性說明
id屬性 ,resultMap标簽的辨別。
type屬性 ,傳回值的全限定類名,或類型别名。
autoMapping屬性 ,值範圍true(預設值)|false, 設定是否啟動自動映射功能,自動映射功能就是自動查找與字段名小寫同名的屬性名,并調用setter方法。而設定為false後,則需要在<code>resultMap</code>内明确注明映射關系才會調用對應的setter方法。
2、基本作用:建立SQL查詢結果字段與實體屬性的映射關系
示例1:通過setter構造領域模型
子元素說明:
id元素 ,用于設定主鍵字段與領域模型屬性的映射關系
result元素 ,用于設定普通字段與領域模型屬性的映射關系
id、result語句屬性配置細節:
屬性
描述
property
需要映射到JavaBean 的屬性名稱。
column
資料表的列名或者标簽别名。
javaType
一個完整的類名,或者是一個類型别名。如果你比對的是一個JavaBean,那MyBatis 通常會自行檢測到。然後,如果你是要映射到一個HashMap,那你需要指定javaType 要達到的目的。
jdbcType
資料表支援的類型清單。這個屬性隻在insert,update 或delete 的時候針對允許空的列有用。JDBC 需要這項,但MyBatis 不需要。如果你是直接針對JDBC 編碼,且有允許空的列,而你要指定這項。
typeHandler
使用這個屬性可以覆寫類型處理器。這項值可以是一個完整的類名,也可以是一個類型别名。
示例2:通過構造函數構造領域模型
constructor元素 ,指定使用指定參數清單的構造函數來執行個體化領域模型。注意:其子元素順序必須與參數清單順序對應
idArg子元素 ,标記該入參為主鍵
arg子元素 ,标記該入參為普通字段(主鍵使用該子元素設定也是可以的)
3、一對一關系、一對多關系查詢
聯合元素用來處理“一對一”的關系。需要指定映射的Java實體類的屬性,屬性的javaType(通常MyBatis 自己會識别)。對應的資料庫表的列名稱。如果想覆寫的話傳回結果的值,需要指定typeHandler。
不同情況需要告訴MyBatis 如何加載一個聯合。MyBatis 可以用兩種方式加載:
select: 執行一個其它映射的SQL 語句傳回一個Java實體類型。較靈活;
resultsMap: 使用一個嵌套的結果映射來處理通過join查詢結果集,映射成Java實體類型。
例如,一個班級對應一個班主任。
首先定義好班級中的班主任 <code>private TeacherEntity teacherEntity;</code>
使用select實作聯合
例:班級實體類中有班主任的屬性,通過聯合在得到一個班級實體時,同時映射出班主任實體。
這樣可以直接複用在TeacherMapper.xml檔案中定義好的查詢teacher根據其ID的select語句。而且不需要修改寫好的SQL語句,隻需要直接修改resultMap即可。
ClassMapper.xml檔案部分内容:
TeacherMapper.xml檔案部分内容:
其中的teacherResultMap請見上面TeacherMapper.xml檔案部分内容中。
聚集元素用來處理“一對多”的關系。需要指定映射的Java實體類的屬性,屬性的javaType(一般為ArrayList);清單中對象的類型ofType(Java實體類);對應的資料庫表的列名稱;
不同情況需要告訴MyBatis 如何加載一個聚集。MyBatis 可以用兩種方式加載:
1. select: 執行一個其它映射的SQL 語句傳回一個Java實體類型。較靈活;
2. resultsMap: 使用一個嵌套的結果映射來處理通過join查詢結果集,映射成Java實體類型。
例如,一個班級有多個學生。
首先定義班級中的學生清單屬性:<code>private List<StudentEntity> studentList;</code>
使用select實作聚集
用法和聯合很類似,差別在于,這是一對多,是以一般映射過來的都是清單。是以這裡需要定義javaType為ArrayList,還需要定義清單中對象的類型ofType,以及必須設定的select的語句名稱(需要注意的是,這裡的查詢student的select語句條件必須是外鍵classID)。
StudentMapper.xml檔案部分内容:
使用resultMap實作聚集
使用resultMap,就需要重寫一個sql,left join學生表。
其中的teacherResultMap請見上面TeacherMapper.xml檔案部分内容中。studentResultMap請見上面StudentMapper.xml檔案部分内容中。
4. 動态映射關系
通過 discriminator子元素 (鑒别器)可以實作動态映射關系資訊的設定。具體示例如下:
情景:查詢學生資訊的seniorHighSchool資訊,若就讀時間during字段值為4、5、6時,則以juniorHighSchool字段作所為seniorHighSchool資訊。
注意:上面關于 discriminator子元素 的 case元素 的 resultType屬性 和 resultMap元素 的 type屬性 ,均不是直指傳回的領域模型類型,而是指定根據判斷條件後得到映射關系,可通過 id子元素 和 result子元素 重寫映射關系。
5. id元素,result元素,idArg元素,arg元素,discriminator元素的共同屬性
javaType屬性 :Java類的全限定名,或别名
jdbcType屬性 :JDBC類型, JDBC類型為CUD操作時列可能為空時進行處理
typeHandler屬性 :指定類型處理器的全限定類名或類型别名
column屬性 :指定SQL查詢結果的字段名或字段别名。将用于JDBC的 resultSet.getString(columnName)