您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“MyBatis @Param注解怎么實現”,內容詳細,步驟清晰,細節處理妥當,希望這篇“MyBatis @Param注解怎么實現”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
先說結論:
當輸入參數只有一個且沒有使用@Param注解時,MyBatis會直接傳遞這個參數;當輸入參數多于一個,或者使用了@Param注解時,MyBatis會將參數封裝在Map中傳遞,這時的Map的key分為以下幾種可能:
Map中會有param1, param2這樣的key,其順序對應輸入參數的順序。無論是否有@Param注解。
對于@Param注解的參數,Map中會保存注解中給定的名字作為key
對于沒有用@Param注解的參數,Map中會用1、2、3 ..這樣的數字作為key,按順序保存輸入參數。
下面來看一下源碼。
首先,判斷一個方法中是否有用@Param注解的參數:
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注解的參數,取出注解中給出的參數名:
private String getParamNameFromAnnotation(Method method, int i, String paramName) { final Object[] paramAnnos = method.getParameterAnnotations()[i]; // 獲取第i個參數的注解 for (Object paramAnno : paramAnnos) { if (paramAnno instanceof Param) { paramName = ((Param) paramAnno).value(); break; } } return paramName; }
注意方法的輸入參數,method表示是哪個方法上,i 表示第幾個參數, paramName是傳進來的參數名,如果該參數沒有用@Param注解,則返回傳進來的paramName。
下面這個方法返回一個TreeMap(有序),其key表示參數的順序,比如key=0代表第0個參數;value表示參數的名字,如果有用@Param注解標注,則為標注的參數名,否則和key相等,即用參數的序號作為參數的名字。
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()); // 參數名,默認為參數的序號 if (hasNamedParameters) { //如果有使用@Param注解,則獲取注解標注的參數名 paramName = getParamNameFromAnnotation(method, i, paramName); // 這里paramName作為參數傳進來,表示默認值 } params.put(i, paramName); } } return params; }
其中hasNamedParameters只是從整個方法的維度,給出該方法是否有使用@Param注解的參數;即使其值為true,具體到某一個參數上面,可能沒有使用@Param注解,因此調用getParamNameFromAnnotation傳入的paramName就作為默認值返回,即參數的序號。
最后將調用方法的參數轉換為MyBatis內部使用的參數:
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方法的輸入參數,這里已經轉換成了數組,其實就是動態代理的invoke方法傳入的參數。
該方法首先對輸入參數進行計數,使用的params就是前面介紹的getParams方法的返回值。
if (!hasNamedParameters && paramCount == 1)
上面的條件判斷,即方法沒有使用@Param注解,且只有一個參數,這時返回
args[params.keySet().iterator().next().intValue()]
即直接將其作為Object返回。
如果上面的條件不滿足的話,首先新建一個Map作為返回值:
final Map<String, Object> param = new ParamMap<Object>();
然后,設置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()]); }
即設置param1、param2這樣的key。
到此為止,需要的參數對象Object就構建完成,其中封裝了Dao傳入的多個參數,并根據參數是否有@Param注解,影響了參數對象的類型(是否是map)。
參數封裝完成之后,下一步將其傳遞給SqlSession。
讀到這里,這篇“MyBatis @Param注解怎么實現”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。