1. 程式人生 > >Mybatis原始碼分析--返回值ResultType和ResultMap

Mybatis原始碼分析--返回值ResultType和ResultMap

這一篇部落格我們來介紹一下Mybatis執行sql語句返回的結果值的到實體物件的對映機制。首先ResultType和ResultMap的使用方式是不同的。

ResultType的使用方式:

resultType的值為實體類

<select id="getUser" parameterType="int" resultType="com.tianjunwei.learn.learn1.entity.User">
         select * from users where id=#{id}
 </select>
ResultMap的使用方式:

首先要定義resultMap的對應關係

<resultMap type="com.tianjunwei.learn.learn1.entity.User" id="user">    
     	<id column="id" property="id" javaType="int" jdbcType="INTEGER"></id>
     	<result column="name" property="names" javaType="string" jdbcType=VARCHAR/>
     	<result column="age" property="age" javaType="int" jdbcType="INTEGER"/>
</resultMap>
接下來直接使用id值resultMap="user"
<select id="getById" parameterType="int" resultMap="user">
     	select * from users where id=#{id} and 1=1
</select>

以上就完成了resultType和resultMap的使用。其實mybatis的預設實現機制是首先會自動使用resultType模式,當表中的欄位值和實體中的名稱不一致時再使用ResultMap方式,如上面的實體User中的names和表中欄位name中的對應關係,所以使用resultType方式實體類中User的names屬性值為空,而使用resultMap方式實體類中就會有值。

當強制使用resultMap而不是ResultType是需要進行如下配置:增加了autoMapping=false,預設值為null

<resultMap type="com.tianjunwei.learn.learn1.entity.User" id="user" autoMapping="false">    
     	<id column="id" property="id" javaType="int" jdbcType="INTEGER"></id>
     	<result column="name" property="names" javaType="string" jdbcType="VARCHAR"/>
     	<result column="age" property="age" javaType="int" jdbcType="INTEGER"/>
     </resultMap>

接下來我們介紹一下其實現機制:

其具體實現是在DefaultResultSetHandler中,在獲取每行資料時會根據resultType或者resultMap來給物件賦值,返回resultObject。

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
    if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(resultObject);
      boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
	  //判斷是否可以使用resultType,如果不做任何額外設定,返回true
      if (shouldApplyAutomaticMappings(resultMap, false)) {
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
      }
	  //使用resultMap方式
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      resultObject = foundValues ? resultObject : null;
      return resultObject;
    }
    return resultObject;
  }