這是mybatis系列第5篇。 說到底Mybatis常見的傳參形式無非是傳遞一個(gè)參數(shù)、Map、Java對(duì)象,亦或是多個(gè)參數(shù)。下面就分別對(duì)這些進(jìn)行講解和說明。 傳遞一個(gè)參數(shù)傳遞一個(gè)參數(shù)相對(duì)來說較為簡(jiǎn)單 用法Mapper接口方法中只有一個(gè)參數(shù),如: UserModel getByName(String name); Mapper xml引用這個(gè)name參數(shù): #{任意合法名稱} 如:#{name}、#{val}、${x}等等寫法都可以引用上面name參數(shù)的值。 傳遞一個(gè)Map參數(shù)用法如果我們需要傳遞的參數(shù)比較多,參數(shù)個(gè)數(shù)是動(dòng)態(tài)的,那么我們可以將這些參數(shù)放在一個(gè)map中,key為參數(shù)名稱,value為參數(shù)的值。在工作中,這種可以說是最常見的。大多數(shù)情況下都可以進(jìn)行使用 Mapper接口中可以這么定義,如: List<UserModel> getByMap(Map<String,Object> map); 如我們傳遞: Map<String, Object> map = new HashMap<>(); map.put("id", 1L); map.put("name", "冢狐"); 對(duì)應(yīng)的mapper xml中可以通過#{map中的key}可以獲取key在map中對(duì)應(yīng)的value的值作為參數(shù),如: SELECT * FROM t_user WHERE id=#{id} OR name = #{name} 傳遞一個(gè)java對(duì)象參數(shù)當(dāng)參數(shù)比較多,但是具體有多少個(gè)參數(shù)我們是確定的時(shí)候,我們可以將這些參數(shù)放在一個(gè)javabean對(duì)象中。這樣也有利于理解,知道需要傳遞那些參數(shù),不想map一樣對(duì)于傳遞的參數(shù)不是很明確。 如我們想通過userId和userName查詢,可以定義一個(gè)dto對(duì)象,屬性添加對(duì)應(yīng)的get、set方法,如: @Getter @Setter @ToString @Builder @NoArgsConstructor @AllArgsConstructor public class UserFindDto { private Long userId; private String userName; } 傳遞java對(duì)象的方式相對(duì)于map的方式更清晰一些,可以明確知道具體有哪些參數(shù),而傳遞map,我們是不知道這個(gè)map中具體需要哪些參數(shù)的,map對(duì)參數(shù)也沒有約束,參數(shù)可以隨意傳,建議多個(gè)參數(shù)的情況下選擇通過java對(duì)象進(jìn)行傳參。 傳遞多個(gè)參數(shù)上面我們介紹的都是傳遞一個(gè)參數(shù),那么是否可以傳遞多個(gè)參數(shù)呢?我們來試試吧。 多參數(shù)mybatis的處理mybatis處理多個(gè)參數(shù)的時(shí)候,會(huì)將多個(gè)參數(shù)封裝到一個(gè)map中,map的key為參數(shù)的名稱,java可以通過反射獲取方法參數(shù)的名稱,下面這個(gè)方法: UserModel getByIdOrName(Long id, String name); 編譯之后,方法參數(shù)的名稱通過反射獲取的并不是id、name,而是arg0、arg1,也就是說編譯之后,方法真實(shí)的參數(shù)名稱會(huì)丟失,會(huì)變成arg+參數(shù)下標(biāo)的格式。 所以上面?zhèn)鬟f的參數(shù)相當(dāng)于傳遞了下面這樣的一個(gè)map: Map<String,Object> map = new HashMap<>(); map.put("arg0",id); map.put("arg1",name); 所以說我們的方法真實(shí)的參數(shù)名稱會(huì)丟失,如果要想使用真實(shí)的參數(shù)名稱,就需要在編譯java代碼使用javac命令的時(shí)候帶上-parameters參數(shù),當(dāng)編譯代碼的時(shí)候加上這個(gè)參數(shù),方法的實(shí)際名稱會(huì)被編譯到class字節(jié)碼文件中,當(dāng)通過反射獲取方法名稱的時(shí)候就不是arg0、arg1這種格式了,而是真實(shí)的參數(shù)名稱:id、name了。 我們來修改一下maven的配置讓maven編譯代碼的時(shí)候加上這個(gè)參數(shù),修改pom.xml中的build元素,這個(gè)元素中加入下面代碼: <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中編譯代碼也加一下這個(gè)參數(shù),操作如下: 點(diǎn)擊File->Settings->Build,Execution,Deployment->Java Compiler,如下圖:
下面我們將xml中的getByIdOrName對(duì)應(yīng)的sql修改成下面這樣: SELECT * FROM t_user WHERE id=#{arg0} OR name = #{arg1} LIMIT 1 使用maven命令重新編譯一下chat01的代碼,cmd命令中mybatis-demo/pom.xml所在目錄執(zhí)行下面命令:
參數(shù)名稱變成了真實(shí)的名稱了,但是還是有param1、param2,方法參數(shù)名稱不管怎么變,編譯方式如何變化,param1, param2始終在這里,這個(gè)param1, param2就是為了應(yīng)對(duì)不同的編譯方式導(dǎo)致參數(shù)名稱而發(fā)生變化的,mybatis內(nèi)部除了將參數(shù)按照名稱->值的方式放入map外,還會(huì)按照參數(shù)的順序放入一些值,這些值的key就是param+參數(shù)位置,這個(gè)位置從1開始的,所以id是第一個(gè)參數(shù),對(duì)應(yīng)的key是param1,name對(duì)應(yīng)的key是param2,value對(duì)應(yīng)的還是參數(shù)的值,所以mybatis對(duì)于參數(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ù)中用@param指定參數(shù)名稱剛才上面講了多參數(shù)傳遞的使用上面,對(duì)參數(shù)名稱和順序有很強(qiáng)的依賴性,容易導(dǎo)致一些嚴(yán)重的錯(cuò)誤。 mybatis也為我們考慮到了這種情況,可以讓我們自己去指定參數(shù)的名稱,通過@param(“參數(shù)名稱”)來給參數(shù)指定名稱。 /** * 通過id或者name查詢 * * @param id * @param name * @return */ UserModel getByIdOrName(@Param("userId") Long id, @Param("userName") String name); 上面我們通過@Param注解給兩個(gè)參數(shù)明確指定了名稱,分別是userId、userName,對(duì)應(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ù)量比較大的時(shí)候,返回一個(gè)List集合占用的內(nèi)存還是比較多的,比如我們想導(dǎo)出很多數(shù)據(jù),實(shí)際上如果我們通過jdbc的方式,遍歷ResultSet的next方法,一條條處理,而不用將其存到List集合中再取處理。 mybatis中也支持我們這么做,可以使用ResultHandler對(duì)象,猶如其名,這個(gè)接口是用來處理結(jié)果的,先看一下其定義: public interface ResultHandler<T> { void handleResult(ResultContext<? extends T> resultContext); } 里面有1個(gè)方法,方法的參數(shù)是ResultContext類型的,這個(gè)也是一個(gè)接口,看一下源碼: public interface ResultContext<T> { T getResultObject(); int getResultCount(); boolean isStopped(); void stop(); } 4個(gè)方法:
ResultContext接口有一個(gè)實(shí)現(xiàn)類org.apache.ibatis.executor.result.DefaultResultContext,mybatis中默認(rèn)會(huì)使用這個(gè)類。 最后
|
|