(五)Mybatis从入门到入土——Mapper接口传参多种方式解析

这是mybatis系列第5篇。

说到底Mybatis常见的传参形式无非是传递一个参数、Map、Java对象,亦或是多个参数。下面就分别对这些进行讲解和说明。

传递一个参数

传递一个参数相对来说较为简单

用法

Mapper接口方法中只有一个参数,如:

UserModel getByName(String name);

Mapper xml引用这个name参数:

#{任意合法名称}

如:#{name}、#{val}、${x}等等写法都可以引用上面name参数的值。

直接使用即可相当的方便和简单

传递一个Map参数

用法

如果我们需要传递的参数比较多,参数个数是动态的,那么我们可以将这些参数放在一个map中,key为参数名称,value为参数的值。在工作中,这种可以说是最常见的。大多数情况下都可以进行使用

Mapper接口中可以这么定义,如:

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

如我们传递:

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

对应的mapper xml中可以通过#{map中的key}可以获取key在map中对应的value的值作为参数,如:

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

传递一个java对象参数

当参数比较多,但是具体有多少个参数我们是确定的时候,我们可以将这些参数放在一个javabean对象中。这样也有利于理解,知道需要传递那些参数,不想map一样对于传递的参数不是很明确。

如我们想通过userId和userName查询,可以定义一个dto对象,属性添加对应的get、set方法,如:

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

传递java对象的方式相对于map的方式更清晰一些,可以明确知道具体有哪些参数,而传递map,我们是不知道这个map中具体需要哪些参数的,map对参数也没有约束,参数可以随意传,建议多个参数的情况下选择通过java对象进行传参。

传递多个参数

上面我们介绍的都是传递一个参数,那么是否可以传递多个参数呢?我们来试试吧。

多参数mybatis的处理

mybatis处理多个参数的时候,会将多个参数封装到一个map中,map的key为参数的名称,java可以通过反射获取方法参数的名称,下面这个方法:

UserModel getByIdOrName(Long id, String name);

编译之后,方法参数的名称通过反射获取的并不是id、name,而是arg0、arg1,也就是说编译之后,方法真实的参数名称会丢失,会变成arg+参数下标的格式。

所以上面传递的参数相当于传递了下面这样的一个map:

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

所以说我们的方法真实的参数名称会丢失,如果要想使用真实的参数名称,就需要在编译java代码使用javac命令的时候带上-parameters参数,当编译代码的时候加上这个参数,方法的实际名称会被编译到class字节码文件中,当通过反射获取方法名称的时候就不是arg0、arg1这种格式了,而是真实的参数名称:id、name了。

我们来修改一下maven的配置让maven编译代码的时候加上这个参数,修改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中编译代码也加一下这个参数,操作如下:

点击File->Settings->Build,Execution,Deployment->Java Compiler,如下图:

下面我们将xml中的getByIdOrName对应的sql修改成下面这样:

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

使用maven命令重新编译一下chat01的代码,cmd命令中mybatis-demo/pom.xml所在目录执行下面命令:

mvn clean compile -pl :chat01

参数名称变成了真实的名称了,但是还是有param1、param2,方法参数名称不管怎么变,编译方式如何变化,param1, param2始终在这里,这个param1, param2就是为了应对不同的编译方式导致参数名称而发生变化的,mybatis内部除了将参数按照名称->值的方式放入map外,还会按照参数的顺序放入一些值,这些值的key就是param+参数位置,这个位置从1开始的,所以id是第一个参数,对应的key是param1,name对应的key是param2,value对应的还是参数的值,所以mybatis对于参数的处理相当于下面过程:

Map<String,Object> map = new HashMap<>();
map.put("反射获取的参数id的名称",id);
map.put("反射获取的参数name的名称",name);
map.put("param1",id);
map.put("param2",name);

使用注意

  • 使用参数名称的方式对编译环境有很强的依赖性,如果编译中加上了-parameters参数,参数实际名称可以直接使用,如果没有加,参数名称就变成arg下标的格式了,这种很容易出错

  • sql中使用param1、param2、paramN这种方式来引用多参数,对参数的顺序依赖性特别强,如果有人把参数的顺序调整了或者调整了参数的个数,后果就是灾难性的,所以这种方式不建议大家使用。

多参数中用@param指定参数名称

刚才上面讲了多参数传递的使用上面,对参数名称和顺序有很强的依赖性,容易导致一些严重的错误。

mybatis也为我们考虑到了这种情况,可以让我们自己去指定参数的名称,通过@param(“参数名称”)来给参数指定名称。

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

上面我们通过@Param注解给两个参数明确指定了名称,分别是userId、userName,对应的user.xml中也做一下调整,如下:

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

ResultHandler作为参数

用法

查询的数量比较大的时候,返回一个List集合占用的内存还是比较多的,比如我们想导出很多数据,实际上如果我们通过jdbc的方式,遍历ResultSet的next方法,一条条处理,而不用将其存到List集合中再取处理。

mybatis中也支持我们这么做,可以使用ResultHandler对象,犹如其名,这个接口是用来处理结果的,先看一下其定义:

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

里面有1个方法,方法的参数是ResultContext类型的,这个也是一个接口,看一下源码:

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

4个方法:

  • getResultObject:获取当前行的结果

  • getResultCount:获取当前结果到第几行了

  • isStopped:判断是否需要停止遍历结果集

  • stop:停止遍历结果集

ResultContext接口有一个实现类org.apache.ibatis.executor.result.DefaultResultContext,mybatis中默认会使用这个类。

最后

  • 如果觉得看完有收获,希望能关注一下,顺便给我点个赞,这将会是我更新的最大动力,感谢各位的支持

(0)

相关推荐

  • 掌握Mybatis动态映射,我可是下了功夫的

    动态 SQL 是 MyBatis 的强大特性之一.如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表 ...

  • mybatis in 查询使用String做条件

    在使用 mybaits 进行 in 查询时 如果传入参数是List或者Array,则直接用foreach 如果参数是String类型的使用in (${xxxx}),不进行编译,直接放进查询条件 例如 ...

  • MyBatis使用注解开发

    MyBatis使用注解开发 面向接口编程 大家之前都学过面向对象编程,也学习过接口,但在真正的开发中,很多时候我们会选择面向接口编程 根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , ...

  • (四)Mybatis从入门到入土——别名、配置文件以及引入mapper

    这是mybatis系列第4篇.没看前文的建议先去[Java冢狐]公众号中查看前文,方便理解和掌握 别名 为什么需要使用别名? 在xml文件中有很多需要类完整的类名的地方,十分的冗长,为了减轻我们的工作 ...

  • (二)MyBatis从入门到入土——开发一个Mybatis项目

    这是mybatis系列第2篇.没看前文的建议先去[Java冢狐]公众号中查看前文,方便理解和掌握这篇文章主要接着前文介绍了如何创建并使用Mybatis. 实战演练 上一篇文章中我们大体介绍了MyBat ...

  • (三)MyBatis从入门到入土——使用详解

    MyBatis使用详解 上篇我们手动开发了一个MyBatis项目,但是我们仅仅是编写了代码,对于整个项目是如何运行以及每个代码的意义都没有仔细的分析和说明,那么接下来我们就开始分析每个代码的意义以及如 ...

  • (六) MyBatis从入门到入土——主键的获取

    这是mybatis系列第六篇.没看前文的建议先去[Java冢狐]公众号中查看前文,方便理解和掌握. 前面五篇把MyBatis的基本用法基本介绍完毕了,强烈推荐大家先把前面五篇看完实际操作完再来看接下来 ...

  • (八)MyBatis从入门到入土——自动映射的使用

    今天我们介绍一下我们一直在使用的但是没有来得及做过多介绍的自动映射. 什么是自动映射? 介绍自动映射之前先看一下手动映射,如下: <resultMap id="orderModelMa ...

  • 围棋定式:入门到入土(85)

    我再不更新,大家可能就已经忘了我并不喜欢打中单了.我只是个臭酱油,给AI包鸡包眼包大药那种. 有时候,你永远不知道自己坑会踩在何处.这个系列,想介绍一些从未体验过的定式大坑.本期开始将陆续介绍小目守角 ...

  • 五运六气入门整理版!!!

    第一章        阴阳五行 五行和阴阳的关系 <道德经>:"道生一,一生二,二生三,三生万物.万物负阴而抱阳,冲气以为和". <易传>:"太极 ...

  • 围棋定式:入门到入土(86)

    我真不是忘了这个系列. 我就是懒. 有时候,你永远不知道自己坑会踩在何处.这个系列,想介绍一些从未体验过的定式大坑.本期开始将陆续介绍小目守角的各种变化,这应该是实战中非常实用的系列. 图1 对于黑1 ...

  • 从入门到入土:MySQL完整学习指南,包教包会!

    一 SQL 介绍 SQL(Structured Query Language),语义是结构化语言, 是一门 ANSI 的标准计算机语言,用来访问和操作数据库系统: 二 数据库介绍 2.1 数据库 我们 ...