天天看點

mybatis ResultMap詳解

前言

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&lt;StudentEntity&gt; 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)