(五)Mybatis從入門到入土——Mapper接口傳參多種方式解析

這是mybatis系列第5篇伊诵。沒看前文的建議先去【Java冢狐】公眾號中查看前文,方便理解和掌握。

說到底Mybatis常見的傳參形式無非是傳遞一個參數(shù)逸寓、Map、Java對象覆山,亦或是多個參數(shù)竹伸。下面就分別對這些進行講解和說明。

傳遞一個參數(shù)

傳遞一個參數(shù)相對來說較為簡單

用法

Mapper接口方法中只有一個參數(shù)簇宽,如:

UserModel getByName(String name);

Mapper xml引用這個name參數(shù):

#{任意合法名稱}

如:#{name}勋篓、#{val}、${x}等等寫法都可以引用上面name參數(shù)的值晦毙。
image.gif

直接使用即可相當(dāng)?shù)姆奖愫秃唵?/p>

傳遞一個Map參數(shù)

用法

如果我們需要傳遞的參數(shù)比較多生巡,參數(shù)個數(shù)是動態(tài)的,那么我們可以將這些參數(shù)放在一個map中见妒,key為參數(shù)名稱孤荣,value為參數(shù)的值。在工作中须揣,這種可以說是最常見的盐股。大多數(shù)情況下都可以進行使用

Mapper接口中可以這么定義,如:

List<UserModel> getByMap(Map<String,Object> map);

如我們傳遞:

Map<String, Object> map = new HashMap<>();
            map.put("id", 1L);
            map.put("name", "冢狐");

對應(yīng)的mapper xml中可以通過#{map中的key}可以獲取key在map中對應(yīng)的value的值作為參數(shù)耻卡,如:

SELECT * FROM t_user WHERE id=#{id} OR name = #{name}

傳遞一個java對象參數(shù)

當(dāng)參數(shù)比較多疯汁,但是具體有多少個參數(shù)我們是確定的時候,我們可以將這些參數(shù)放在一個javabean對象中卵酪。這樣也有利于理解幌蚊,知道需要傳遞那些參數(shù),不想map一樣對于傳遞的參數(shù)不是很明確溃卡。

如我們想通過userId和userName查詢溢豆,可以定義一個dto對象,屬性添加對應(yīng)的get瘸羡、set方法漩仙,如:

@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserFindDto {
    private Long userId;
    private String userName;
}

傳遞java對象的方式相對于map的方式更清晰一些,可以明確知道具體有哪些參數(shù),而傳遞map队他,我們是不知道這個map中具體需要哪些參數(shù)的卷仑,map對參數(shù)也沒有約束,參數(shù)可以隨意傳麸折,建議多個參數(shù)的情況下選擇通過java對象進行傳參锡凝。

傳遞多個參數(shù)

上面我們介紹的都是傳遞一個參數(shù),那么是否可以傳遞多個參數(shù)呢磕谅?我們來試試吧私爷。

多參數(shù)mybatis的處理

mybatis處理多個參數(shù)的時候,會將多個參數(shù)封裝到一個map中膊夹,map的key為參數(shù)的名稱衬浑,java可以通過反射獲取方法參數(shù)的名稱,下面這個方法:

UserModel getByIdOrName(Long id, String name);

編譯之后放刨,方法參數(shù)的名稱通過反射獲取的并不是id工秩、name,而是arg0进统、arg1助币,也就是說編譯之后,方法真實的參數(shù)名稱會丟失螟碎,會變成arg+參數(shù)下標的格式眉菱。

所以上面?zhèn)鬟f的參數(shù)相當(dāng)于傳遞了下面這樣的一個map:

Map<String,Object> map = new HashMap<>();
map.put("arg0",id);
map.put("arg1",name);

所以說我們的方法真實的參數(shù)名稱會丟失,如果要想使用真實的參數(shù)名稱掉分,就需要在編譯java代碼使用javac命令的時候帶上-parameters參數(shù)俭缓,當(dāng)編譯代碼的時候加上這個參數(shù),方法的實際名稱會被編譯到class字節(jié)碼文件中酥郭,當(dāng)通過反射獲取方法名稱的時候就不是arg0华坦、arg1這種格式了,而是真實的參數(shù)名稱:id不从、name了惜姐。

我們來修改一下maven的配置讓maven編譯代碼的時候加上這個參數(shù),修改pom.xml中的build元素椿息,這個元素中加入下面代碼:

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
            <compilerArgs>
                <arg>-parameters</arg>
            </compilerArgs>
        </configuration>
    </plugin>
</plugins>

idea中編譯代碼也加一下這個參數(shù)歹袁,操作如下:

點擊File->Settings->Build,Execution,Deployment->Java Compiler,如下圖:

image.gif

image

下面我們將xml中的getByIdOrName對應(yīng)的sql修改成下面這樣:

SELECT * FROM t_user WHERE id=#{arg0} OR name = #{arg1} LIMIT 1

使用maven命令重新編譯一下chat01的代碼寝优,cmd命令中mybatis-demo/pom.xml所在目錄執(zhí)行下面命令:

mvn clean compile -pl :chat01

參數(shù)名稱變成了真實的名稱了宇攻,但是還是有param1、param2倡勇,方法參數(shù)名稱不管怎么變,編譯方式如何變化,param1, param2始終在這里妻熊,這個param1, param2就是為了應(yīng)對不同的編譯方式導(dǎo)致參數(shù)名稱而發(fā)生變化的夸浅,mybatis內(nèi)部除了將參數(shù)按照名稱->值的方式放入map外,還會按照參數(shù)的順序放入一些值扔役,這些值的key就是param+參數(shù)位置帆喇,這個位置從1開始的,所以id是第一個參數(shù)亿胸,對應(yīng)的key是param1坯钦,name對應(yīng)的key是param2,value對應(yīng)的還是參數(shù)的值侈玄,所以mybatis對于參數(shù)的處理相當(dāng)于下面過程:

Map<String,Object> map = new HashMap<>();
map.put("反射獲取的參數(shù)id的名稱",id);
map.put("反射獲取的參數(shù)name的名稱",name);
map.put("param1",id);
map.put("param2",name);

使用注意

  • 使用參數(shù)名稱的方式對編譯環(huán)境有很強的依賴性婉刀,如果編譯中加上了-parameters參數(shù),參數(shù)實際名稱可以直接使用序仙,如果沒有加突颊,參數(shù)名稱就變成arg下標的格式了,這種很容易出錯
  • sql中使用param1潘悼、param2律秃、paramN這種方式來引用多參數(shù),對參數(shù)的順序依賴性特別強治唤,如果有人把參數(shù)的順序調(diào)整了或者調(diào)整了參數(shù)的個數(shù)棒动,后果就是災(zāi)難性的,所以這種方式不建議大家使用宾添。

多參數(shù)中用@param指定參數(shù)名稱

剛才上面講了多參數(shù)傳遞的使用上面船惨,對參數(shù)名稱和順序有很強的依賴性,容易導(dǎo)致一些嚴重的錯誤辞槐。

mybatis也為我們考慮到了這種情況掷漱,可以讓我們自己去指定參數(shù)的名稱,通過@param(“參數(shù)名稱”)來給參數(shù)指定名稱榄檬。

/**
 * 通過id或者name查詢
 *
 * @param id
 * @param name
 * @return
 */
UserModel getByIdOrName(@Param("userId") Long id, @Param("userName") String name);

上面我們通過@Param注解給兩個參數(shù)明確指定了名稱卜范,分別是userId、userName鹿榜,對應(yīng)的user.xml中也做一下調(diào)整海雪,如下:

<!-- 通過id或者name查詢 -->
<select id="getByIdOrName" resultType="zhonghu.mybatis.chat01.UserModel">
    <![CDATA[
    SELECT * FROM user WHERE id=#{userId} OR name = #{userName} LIMIT 1
    ]]>
</select>

ResultHandler作為參數(shù)

用法

查詢的數(shù)量比較大的時候,返回一個List集合占用的內(nèi)存還是比較多的舱殿,比如我們想導(dǎo)出很多數(shù)據(jù)奥裸,實際上如果我們通過jdbc的方式,遍歷ResultSet的next方法沪袭,一條條處理湾宙,而不用將其存到List集合中再取處理。

mybatis中也支持我們這么做,可以使用ResultHandler對象侠鳄,猶如其名埠啃,這個接口是用來處理結(jié)果的,先看一下其定義:

public interface ResultHandler<T> {
  void handleResult(ResultContext<? extends T> resultContext);
}

里面有1個方法伟恶,方法的參數(shù)是ResultContext類型的碴开,這個也是一個接口,看一下源碼:

public interface ResultContext<T> {
  T getResultObject();
  int getResultCount();
  boolean isStopped();
  void stop();
}

4個方法:

  • getResultObject:獲取當(dāng)前行的結(jié)果
  • getResultCount:獲取當(dāng)前結(jié)果到第幾行了
  • isStopped:判斷是否需要停止遍歷結(jié)果集
  • stop:停止遍歷結(jié)果集

ResultContext接口有一個實現(xiàn)類org.apache.ibatis.executor.result.DefaultResultContext博秫,mybatis中默認會使用這個類潦牛。

最后

  • 如果覺得看完有收獲,希望能關(guān)注一下挡育,順便給我點個贊巴碗,這將會是我更新的最大動力,感謝各位的支持
  • 歡迎各位關(guān)注我的公眾號【java冢狐】静盅,專注于java和計算機基礎(chǔ)知識良价,保證讓你看完有所收獲,不信你打我
  • 求一鍵三連:點贊蒿叠、轉(zhuǎn)發(fā)明垢、在看。
  • 如果看完有不同的意見或者建議市咽,歡迎多多評論一起交流痊银。感謝各位的支持以及厚愛。

——我是冢狐施绎,和你一樣熱愛編程溯革。

歡迎關(guān)注公眾號“ Java冢狐”,獲取最新消息

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谷醉,一起剝皮案震驚了整個濱河市致稀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俱尼,老刑警劉巖抖单,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異遇八,居然都是意外死亡矛绘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門刃永,熙熙樓的掌柜王于貴愁眉苦臉地迎上來货矮,“玉大人,你說我怎么就攤上這事斯够∏裘担” “怎么了喧锦?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長劫灶。 經(jīng)常有香客問我裸违,道長,這世上最難降的妖魔是什么本昏? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮枪汪,結(jié)果婚禮上涌穆,老公的妹妹穿的比我還像新娘。我一直安慰自己雀久,他們只是感情好宿稀,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赖捌,像睡著了一般祝沸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上越庇,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天罩锐,我揣著相機與錄音,去河邊找鬼卤唉。 笑死涩惑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桑驱。 我是一名探鬼主播竭恬,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼熬的!你這毒婦竟也來了痊硕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤押框,失蹤者是張志新(化名)和其女友劉穎岔绸,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體强戴,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡亭螟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了骑歹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片预烙。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖道媚,靈堂內(nèi)的尸體忽然破棺而出扁掸,到底是詐尸還是另有隱情翘县,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布谴分,位于F島的核電站锈麸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏牺蹄。R本人自食惡果不足惜忘伞,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沙兰。 院中可真熱鬧氓奈,春花似錦、人聲如沸鼎天。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斋射。三九已至育勺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罗岖,已是汗流浹背涧至。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呀闻,地道東北人化借。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像捡多,于是被迫代替她去往敵國和親蓖康。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容