MyBatis @Param注解的實現(xiàn)
先說結(jié)論:
當(dāng)輸入?yún)?shù)只有一個且沒有使用@Param注解時,MyBatis會直接傳遞這個參數(shù);當(dāng)輸入?yún)?shù)多于一個,或者使用了@Param注解時,MyBatis會將參數(shù)封裝在Map中傳遞,這時的Map的key分為以下幾種可能:
- Map中會有param1, param2這樣的key,其順序?qū)?yīng)輸入?yún)?shù)的順序。無論是否有@Param注解。
- 對于@Param注解的參數(shù),Map中會保存注解中給定的名字作為key
- 對于沒有用@Param注解的參數(shù),Map中會用1、2、3 ..這樣的數(shù)字作為key,按順序保存輸入?yún)?shù)。
下面來看一下源碼。
首先,判斷一個方法中是否有用@Param注解的參數(shù):
private boolean hasNamedParams(Method method) {
final Object[][] paramAnnos = method.getParameterAnnotations();
for (Object[] paramAnno : paramAnnos) {
for (Object aParamAnno : paramAnno) {
if (aParamAnno instanceof Param) {
return true;
}
}
}
return false;
}
如果有用@Param注解的參數(shù),取出注解中給出的參數(shù)名:
private String getParamNameFromAnnotation(Method method, int i, String paramName) {
final Object[] paramAnnos = method.getParameterAnnotations()[i]; // 獲取第i個參數(shù)的注解
for (Object paramAnno : paramAnnos) {
if (paramAnno instanceof Param) {
paramName = ((Param) paramAnno).value();
break;
}
}
return paramName;
}
注意方法的輸入?yún)?shù),method表示是哪個方法上,i 表示第幾個參數(shù), paramName是傳進來的參數(shù)名,如果該參數(shù)沒有用@Param注解,則返回傳進來的paramName。
下面這個方法返回一個TreeMap(有序),其key表示參數(shù)的順序,比如key=0代表第0個參數(shù);value表示參數(shù)的名字,如果有用@Param注解標(biāo)注,則為標(biāo)注的參數(shù)名,否則和key相等,即用參數(shù)的序號作為參數(shù)的名字。
private SortedMap<Integer, String> getParams(Method method, boolean hasNamedParameters) {
final SortedMap<Integer, String> params = new TreeMap<Integer, String>();
final Class<?>[] argTypes = method.getParameterTypes();
for (int i = 0; i < argTypes.length; i++) {
if (!RowBounds.class.isAssignableFrom(argTypes[i]) && !ResultHandler.class.isAssignableFrom(argTypes[i])) {
String paramName = String.valueOf(params.size()); // 參數(shù)名,默認(rèn)為參數(shù)的序號
if (hasNamedParameters) { //如果有使用@Param注解,則獲取注解標(biāo)注的參數(shù)名
paramName = getParamNameFromAnnotation(method, i, paramName); // 這里paramName作為參數(shù)傳進來,表示默認(rèn)值
}
params.put(i, paramName);
}
}
return params;
}
其中hasNamedParameters只是從整個方法的維度,給出該方法是否有使用@Param注解的參數(shù);即使其值為true,具體到某一個參數(shù)上面,可能沒有使用@Param注解,因此調(diào)用getParamNameFromAnnotation傳入的paramName就作為默認(rèn)值返回,即參數(shù)的序號。
最后將調(diào)用方法的參數(shù)轉(zhuǎn)換為MyBatis內(nèi)部使用的參數(shù):
public Object convertArgsToSqlCommandParam(Object[] args) {
final int paramCount = params.size();
if (args == null || paramCount == 0) {
return null;
} else if (!hasNamedParameters && paramCount == 1) {
return args[params.keySet().iterator().next().intValue()];
} else {
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
for (Map.Entry<Integer, String> entry : params.entrySet()) {
param.put(entry.getValue(), args[entry.getKey().intValue()]);
// issue #71, add param names as param1, param2...but ensure backward compatibility
final String genericParamName = "param" + String.valueOf(i + 1);
if (!param.containsKey(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
其中args為Dao方法的輸入?yún)?shù),這里已經(jīng)轉(zhuǎn)換成了數(shù)組,其實就是動態(tài)代理的invoke方法傳入的參數(shù)。
該方法首先對輸入?yún)?shù)進行計數(shù),使用的params就是前面介紹的getParams方法的返回值。
if (!hasNamedParameters && paramCount == 1)
上面的條件判斷,即方法沒有使用@Param注解,且只有一個參數(shù),這時返回
args[params.keySet().iterator().next().intValue()]
即直接將其作為Object返回。
如果上面的條件不滿足的話,首先新建一個Map作為返回值:
final Map<String, Object> param = new ParamMap<Object>();
然后,設(shè)置map的key和value:
param.put(entry.getValue(), args[entry.getKey().intValue()]);
然后為了兼容性,做了如下操作
final String genericParamName = "param" + String.valueOf(i + 1);
if (!param.containsKey(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
即設(shè)置param1、param2這樣的key。
到此為止,需要的參數(shù)對象Object就構(gòu)建完成,其中封裝了Dao傳入的多個參數(shù),并根據(jù)參數(shù)是否有@Param注解,影響了參數(shù)對象的類型(是否是map)。
參數(shù)封裝完成之后,下一步將其傳遞給SqlSession。
到此這篇關(guān)于MyBatis @Param注解的實現(xiàn)的文章就介紹到這了,更多相關(guān)MyBatis @Param注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java?Runnable和Thread實現(xiàn)多線程哪個更好你知道嗎
這篇文章主要為大家詳細(xì)介紹了Java?Runnable和Thread實現(xiàn)多線程哪個更好,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助<BR>2022-03-03
Java向數(shù)據(jù)庫插入中文出現(xiàn)亂碼解決方案
這篇文章主要介紹了Java向數(shù)據(jù)庫插入中文出現(xiàn)亂碼解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08
詳解MyBatis resultType與resultMap中的幾種返回類型
本文主要介紹了MyBatis resultType與resultMap中的幾種返回類型,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
Java zookeeper圖形化工具ZooInspector用法詳解
這篇文章主要介紹了Java zookeeper圖形化工具ZooInspector用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
SpringBoot項目中出現(xiàn)不同端口跨域問題的解決方法
這篇文章主要介紹了SpringBoot項目中出現(xiàn)不同端口跨域問題的解決方法,文中介紹了兩種解決方法,并給出了詳細(xì)的代碼供大家參考,具有一定的參考價值,需要的朋友可以參考下2024-03-03
Spring Core核心類庫的功能與應(yīng)用實踐分析
本文詳細(xì)介紹了SpringCore核心類庫的功能、應(yīng)用實踐和底層原理,SpringCore提供了控制反轉(zhuǎn)(IOC)、依賴注入(DI)、Bean管理以及JNDI、定時任務(wù)等企業(yè)級功能,文章通過多個Java示例展示了SpringCore的應(yīng)用,感興趣的朋友跟隨小編一起看看吧2024-12-12
詳述IntelliJ IDEA遠(yuǎn)程調(diào)試Tomcat的方法(圖文)
本篇文章主要介紹了詳述IntelliJ IDEA遠(yuǎn)程調(diào)試Tomcat的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12

