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相等,即用引數的序號作為引數的名字。
其中hasNamedParameters只是從整個方法的維度,給出該方法是否有使用@Param註解的引數;即使其值為true,具體到某一個引數上面,可能沒有使用@Param註解,因此呼叫getParamNameFromAnnotation傳入的paramName就作為預設值返回,即引數的序號。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; }
最後將呼叫方法的引數轉換為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註解
轉自:https://blog.csdn.net/mrqiang9001/article/details/79520436 Mybatis 作為一個輕量級的資料持久化框架,目前(2018)的應用非常廣泛,基本可以取代Hibernate。關於 @param 這個註解的使用,作者這裡整理了一些筆記。
關於Mybatis的@Param註解 及 mybatis Mapper中各種傳遞引數的方法
原文:https://blog.csdn.net/mrqiang9001/article/details/79520436 關於Mybatis的@Param註解 Mybatis 作為一個輕量級的資料持久化框架,目前(2018)的應用非常廣泛,基本可以取代Hiberna
@Param註解 關於mybatis的@Param註解和引數
關於mybatis的@Param註解和引數 引用 https://www.cnblogs.com/whisper527/p/6568028.html 薇飄意 1,使用@Param註解 當以下面的方式進行寫SQL語句時:  
Mybatis中@Param註解詳細使用和原理分析
對於目前市場上火爆的持久層框架MyBatis相信大家在工作中肯定是用得很多,但是你對其mapper介面代理物件和其方法上的@Param註解又瞭解多少呢? 廢話不多說,接來下就給大家來分析下 MapperRegistry MapperRegistry是用於註冊和快
關於mybatis的@Param註解和引數
1,使用@Param註解 當以下面的方式進行寫SQL語句時: @Select("select column from table where userid = #{userid} ") public int selectColumn(int userid);
mybatis的@Param註解和引數
1,使用@Param註解 點選開啟連結當以下面的方式進行寫SQL語句時: @Select("select column from table where userid = #{userid} ") public int selectC
MyBatis 中 @Param 註解的四種使用場景,最後一種經常被人忽略!
有一些小夥伴覺得 MyBatis 只有方法中存在多個引數的時候,才需要新增 @Param 註解,其實這個理解是不準確的。即使 MyBatis 方法只有一個引數,也可能會用到 @Param 註解。 但是,在你總結出規律之前,你可能會覺得莫名其妙,有的時候一個引數明明不用新增 @Param 註解,有的時候,卻需
MyBatis原始碼-關於@Param註解
先說結論:當輸入引數只有一個且沒有使用@Param註解時,MyBatis會直接傳遞這個引數;當輸入引數多於一個,或者使用了@Param註解時,MyBatis會將引數封裝在Map中傳遞,這時的Map的key分為以下幾種可能:Map中會有param1, param2這樣的key,
mybatis使用@param("xxx")註解傳參和不使用的區別
color class myba rdo rec delete ger con inter public interface SystemParameterMapper { int deleteByPrimaryKey(Integer id); int
MyBatis中的@Param註解和引數
Mybatis 作為一個輕量級的資料持久化框架,目前應用非常廣泛,基本可以取代Hibernate。 關於Mybatis中的@Param 註解,官方文件:http://www.mybatis.org/mybatis-3/zh/java-api.html 其中關於 @param部分的說明是:
mybatis傳多個引數(不使用@param註解情況下),3.4.2版本之後出現#{0}-#{n}引數繫結異常
解決方案: 在mybatis配置檔案中宣告setting屬性的useActualParamName 引數值為false **
mybatis的對映檔案當入參時Map時應注意,還有多個入參用@Param註解出現繫結失敗時
<select id="findPostsBetweenRange" parameterType="java.util.Map" resultMap="PostResultMap"> SELECT p.id as post_id,
@Param註解在mybatis中的使用及傳入引數總結
例項一 @Param註解單一屬性 dao層示例 Public User selectUser(@param(“userName”) String name,@param(“userpassword”) String password); xml對映對應示例 <
mybatis傳多個引數(不使用@param註解情況下),3.4.2版本之後使用#{0}-#{n}引起的引數繫結異常,以及settings屬性中useActualParamName的作用。
解決方案: mybatis的xml配置檔案中宣告settings屬性的useActualParamName引數值為false <setting name="useActualParamName" value="false" /> 程式碼展示
MyBatis原始碼分析之@ResultMap註解詳解
MyBatis原始碼分析之@ResultMap註解詳解 在前一篇文章講**@MapKey註解時,我原想將@ResultMap註解也一起拿出來說一下,但是發現@ResultMap解析載入原始碼非常多,想想就不在一篇文章中講了,分開單獨來說,這一篇就來徹底探索一下@ResultMap**
MyBatis原始碼分析之@SelectProvider註解使用詳解
MyBatis原始碼分析之@SelectProvider註解使用詳解 之前講了MyBatis的配置、plugin、Select查詢,還有@MapKey註解的使用與原理,還有返回@ResultMap等等,我原想直接從MyBatis的快取開始說起,但是想想還是得說一下MyBatis中的@
mybatis學習教程——@Param註解使用
當介面引數比較多的時候,可以使用JavaBean來封裝引數,當引數比較少的情況,可以使用Map型別或者使用@Param註解1.userMapper介面類package com.aruisi.mybatis.mapper; import com.aruisi.mybatis.
mybatis原始碼學習--spring+mybatis註解方式為什麼mybatis的dao介面不需要實現類
相信大家在剛開始學習mybatis註解方式,或者spring+mybatis註解方式的時候,一定會有一個疑問,為什麼mybatis的dao介面只需要一個介面,不需要實現類,就可以正常使用,筆者最開始的時候也會有這種疑問,當時在網上查了很多資料,也問過公
Spring boot 學習六 spring 繼承 mybatis (基於註解)
oot provide rom 構造 per 來看 color 如何使用 語言 MyBatis提供了多個註解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,這些都是建立動態語言和讓MyBat
Spring Boot MyBatis升級篇-註解-動態SQL(if test)-方案二:@Provider(8)
指定 ins pro builder except uil test 就是 class 1)動態語言註解(2)@Provider使用思路(3)@SelectProvider小試牛刀(4)@SelectProvider初露鋒芒(5)@SelectProvider過關斬將(6)