亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

【Mybatis系列】從源碼角度理解Mybatis字段映射-駝峰式命名

qiangdada / 1851人閱讀

摘要:主要有三種方案駝峰式命名開(kāi)關(guān),或者不開(kāi),數(shù)據(jù)庫(kù)列和字段名全一致。開(kāi)啟開(kāi)配置項(xiàng)后,在匹配時(shí),能夠根據(jù)數(shù)據(jù)庫(kù)列名找到對(duì)應(yīng)對(duì)應(yīng)的駝峰式命名后的字段。經(jīng)過(guò)若干次中途崩潰,我終于寫(xiě)完了駝峰式命名開(kāi)關(guān)下,我們是如何完成數(shù)據(jù)庫(kù)列和字段名的映射的。

在上篇博客-[[JDBC] 處理ResultSet,構(gòu)建Java對(duì)象](https://my.oschina.net/kailun...中提到,我們需要分析Mybatis在轉(zhuǎn)換Result到需要的Java業(yè)務(wù)對(duì)象時(shí)做的三件事,如下:

解決了數(shù)據(jù)庫(kù)列名到Java列名的映射。

解決了數(shù)據(jù)庫(kù)類(lèi)型到Java類(lèi)型的轉(zhuǎn)換工作。

在轉(zhuǎn)換過(guò)程中具備一定的容錯(cuò)能力。

其實(shí)核心就是:

數(shù)據(jù)庫(kù)中的列名怎么和對(duì)象中的字段對(duì)應(yīng)起來(lái)。

數(shù)據(jù)庫(kù)中的列的類(lèi)型怎么轉(zhuǎn)換到合適的Java類(lèi)型,不引起轉(zhuǎn)換失敗。

今天我們先來(lái)看第一點(diǎn),數(shù)據(jù)庫(kù)中的列名怎么和對(duì)象中的字段對(duì)應(yīng)起來(lái)。首先是日常PO(Persistant Object) CityPO,里面有五個(gè)字段。

public class CityPO {
    Integer id;
    Long cityId;
    String cityName;
    String cityEnName;
    String cityPyName;

本次要查詢(xún)的數(shù)據(jù)庫(kù)中的列名如下所示。

mysql> mysql> desc SU_City;
+--------------+-------------+------+-----+-------------------+-----------------------------+
| Field        | Type        | Null | Key | Default           | Extra                       |
+--------------+-------------+------+-----+-------------------+-----------------------------+
| id           | int(11)     | NO   | PRI | NULL              | auto_increment              |
| city_id      | int(11)     | NO   | UNI | NULL              |                             |
| city_name    | varchar(20) | NO   |     |                   |                             |
| city_en_name | varchar(20) | NO   |     |                   |                             |
| city_py_name | varchar(50) | NO   |     |                   |                             |
| create_time  | datetime    | NO   |     | CURRENT_TIMESTAMP |                             |
| updatetime   | datetime    | NO   | MUL | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+--------------+-------------+------+-----+-------------------+-----------------------------+
7 rows in set (0.01 sec)

我們是按照駝峰式命名,把數(shù)據(jù)庫(kù)中的列名對(duì)應(yīng)到了對(duì)象的字段名。如下是Mybatis的接口類(lèi)和映射文件。

public interface CityMapper {

    CityPO selectCity(int id);
}



    

在上面的映射文件中,namespace指定了這個(gè)接口類(lèi)的全限定類(lèi)名,緊隨其后的select代表是select語(yǔ)句,id是接口類(lèi)中函數(shù)的名字,resultType代表了從這條語(yǔ)句中返回的期望類(lèi)型的類(lèi)的完全限定名或別名,在此例子中是我們的業(yè)務(wù)對(duì)象CityPO的類(lèi)路徑。

主要有三種方案

駝峰式命名開(kāi)關(guān),或者不開(kāi),數(shù)據(jù)庫(kù)列和字段名全一致。

Select時(shí)指定AS。

resultMap 最穩(wěn)健。

這篇主要看一下第一種,附上示例和部分源碼走讀。

駝峰命名開(kāi)關(guān)。
因?yàn)镃ityPO的列名是完全根據(jù)數(shù)據(jù)庫(kù)列名駝峰式命名后得到的,因此Mybatis提供了一個(gè)配置項(xiàng)。開(kāi)啟開(kāi)配置項(xiàng)后,在匹配時(shí),能夠根據(jù)數(shù)據(jù)庫(kù)列名找到對(duì)應(yīng)對(duì)應(yīng)的駝峰式命名后的字段。


    
    

我們從源碼角度解讀一下,Mybat處理ResultSet的映射默認(rèn)都在DefaultResultSetHandler中完成。
處理行數(shù)據(jù)的時(shí)候的時(shí)候主要在下面?的函數(shù)里進(jìn)行,由于我們?cè)谟成湮募袥](méi)有定義額外的ResultMap,因此會(huì)直接進(jìn)入else分支的代碼。

public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
    if (resultMap.hasNestedResultMaps()) {
      ensureNoRowBounds();
      checkResultHandler();
      handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    } else {
      handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    }
}

進(jìn)入handleRowValuesForSimpleResultMap中,主要處理函數(shù)如下,在這里完成了對(duì)象的生成及賦值。

Object rowValue = getRowValue(rsw, discriminatedResultMap); 

在這里先創(chuàng)建了對(duì)象的實(shí)例,然后獲取了對(duì)象的元信息,為反射賦值做準(zhǔn)備。

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(rowValue);
      boolean foundValues = this.useConstructorMappings;
      if (shouldApplyAutomaticMappings(resultMap, false)) {
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      rowValue = (foundValues || configuration.isReturnInstanceForEmptyRow()) ? rowValue : null;
    }
    return rowValue;
  }

在applyAutomaticMappings完成了整個(gè)過(guò)程,我們進(jìn)去探一探。

就是下面這個(gè)函數(shù)創(chuàng)建好了映射關(guān)系,這個(gè)函數(shù)的下半部分是完成賦值的,映射的部分下次會(huì)詳細(xì)分析。

List autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix); 

在這個(gè)方法里,上半部分是生成了數(shù)據(jù)庫(kù)的列名,在這個(gè)函數(shù)中找到了對(duì)應(yīng)的字段名。

final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase()); 

我們進(jìn)去看一看,它傳進(jìn)了生成好的數(shù)據(jù)庫(kù)列名,傳進(jìn)了前面提到的是否根據(jù)駝峰式命名映射開(kāi)關(guān)的值。

事實(shí)證明,真的很簡(jiǎn)單,往下看,就是把下劃線都去了。

public String findProperty(String name, boolean useCamelCaseMapping) {
    if (useCamelCaseMapping) {
      name = name.replace("_", "");
    }
    return findProperty(name);
  }

隱隱覺(jué)得是不是大小寫(xiě)不敏感啊,繼續(xù)往下看,這里返回找到的字段名。

 private StringBuilder buildProperty(String name, StringBuilder builder) {
      ..........
      String propertyName = reflector.findPropertyName(name);
      if (propertyName != null) {
        builder.append(propertyName);
      }
    }
    return builder;
  }

好了,真相大白,就是大小寫(xiě)不敏感的。

public String findPropertyName(String name) {
    return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH));
}

所以如果你數(shù)據(jù)庫(kù)里字段是city_id,city_Id,大寫(xiě)I,那么可能會(huì)有問(wèn)題吧,不過(guò)仔細(xì)想想,誰(shuí)會(huì)吃力不討好干這種事情,硬要處理成標(biāo)準(zhǔn)的駝峰式命名也可以啦,不過(guò)感覺(jué)必要性不大。

經(jīng)過(guò)若干次中途崩潰,我終于寫(xiě)完了駝峰式命名開(kāi)關(guān)下,我們是如何完成數(shù)據(jù)庫(kù)列和字段名的映射的。后面的博文會(huì)繼續(xù)看看后續(xù)兩種方案以及DDL時(shí)對(duì)象字段是如何賦值到Sql語(yǔ)句中。

如果想進(jìn)一步了解的話(huà),歡迎關(guān)注我的微信公眾號(hào)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/67416.html

相關(guān)文章

  • Mybatis系列源碼角度理解Mybatis字段映射-AS&ResultMap

    摘要:北京解決辦法在字段的時(shí)候使用,下面是改動(dòng)后的映射文件。北京那么我們來(lái)看看它是如何生效的,主要的代碼在哪里。源碼層面的話(huà),依舊在的中處理返回集合??偨Y(jié)大致上,完成映射主要是兩種方式。使用預(yù)先定義好映射關(guān)系,也是最后根據(jù)和反射,完成字段的賦值。 前言 考慮到在Select時(shí)使用AS和方案一其實(shí)沒(méi)什么差別,在介紹ResultMap之前,順便帶過(guò)一下。 方案二-Select .... AS 當(dāng)...

    Zhuxy 評(píng)論0 收藏0
  • Mybatis系列源碼角度理解Mybatis的數(shù)據(jù)轉(zhuǎn)換器TypeHandler

    摘要:無(wú)論是在預(yù)處理語(yǔ)句中設(shè)置一個(gè)參數(shù)時(shí),還是從結(jié)果集中取出一個(gè)值時(shí),都會(huì)用類(lèi)型處理器將獲取的值以合適的方式轉(zhuǎn)換成類(lèi)型。這個(gè)抽象類(lèi)實(shí)現(xiàn)了接口,這個(gè)接口主要定義了類(lèi)型轉(zhuǎn)換的幾種操作。至于這個(gè)抽象類(lèi)繼承的,主要是提供了獲取這個(gè)具體是哪個(gè)類(lèi)型。 TypeHandlers 無(wú)論是 MyBatis 在預(yù)處理語(yǔ)句(PreparedStatement)中設(shè)置一個(gè)參數(shù)時(shí),還是從結(jié)果集中取出一個(gè)值時(shí), 都會(huì)用...

    Edison 評(píng)論0 收藏0
  • Mybatis系列源碼角度深度理解Mybatis的緩存特性

    摘要:一級(jí)緩存介紹及相關(guān)配置。在這個(gè)章節(jié),我們學(xué)習(xí)如何使用的一級(jí)緩存。一級(jí)緩存實(shí)驗(yàn)配置完畢后,通過(guò)實(shí)驗(yàn)的方式了解一級(jí)緩存的效果。源碼分析了解具體的工作流程后,我們隊(duì)查詢(xún)相關(guān)的核心類(lèi)和一級(jí)緩存的源碼進(jìn)行走讀。 我,后端Java工程師,現(xiàn)在美團(tuán)點(diǎn)評(píng)工作。愛(ài)健身,愛(ài)技術(shù),也喜歡寫(xiě)點(diǎn)文字。個(gè)人網(wǎng)站: http://kailuncen.me公眾號(hào): KailunTalk (凱倫說(shuō)) 前言 本文主要涉及...

    Ku_Andrew 評(píng)論0 收藏0
  • Mybatis系列源碼角度深度理解Mybatis的緩存特性

    摘要:一級(jí)緩存介紹及相關(guān)配置。在這個(gè)章節(jié),我們學(xué)習(xí)如何使用的一級(jí)緩存。一級(jí)緩存實(shí)驗(yàn)配置完畢后,通過(guò)實(shí)驗(yàn)的方式了解一級(jí)緩存的效果。源碼分析了解具體的工作流程后,我們隊(duì)查詢(xún)相關(guān)的核心類(lèi)和一級(jí)緩存的源碼進(jìn)行走讀。 我,后端Java工程師,現(xiàn)在美團(tuán)點(diǎn)評(píng)工作。愛(ài)健身,愛(ài)技術(shù),也喜歡寫(xiě)點(diǎn)文字。個(gè)人網(wǎng)站: http://kailuncen.me公眾號(hào): KailunTalk (凱倫說(shuō)) 前言 本文主要涉及...

    young.li 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<