前段时间换工作,我去了一家中型互联网公司面试Java开发。技术面上来就是一通熟悉的问题,Spring、Redis、线程池,我答得如鱼得水。轮到MyBatis,我信心满满,毕竟项目里天天用。

结果,面试官看着我说:“那我问个简单点的吧——在Mapper中,如何传递多个参数?”

当时我还在想,这还不简单?用逗号传呗!但我话到嘴边又卡住了——等等,MyBatis的Mapper接口里,方法参数能随便传多个吗?

于是,我硬着头皮答:“我用Map传的……”

面试官点头,又接着问:

“除了Map,你还用过什么方式?@Param你用过吗?那多个参数不用注解的时候,你知道默认怎么传进去的吗?”

就这样,三个问题连珠炮,我脸上写满了‘别问了,我回去查一下’。

回去之后,我立刻翻源码、看官网、写 demo,才把这个“基础问题”吃透。今天就来跟大家完整讲讲 MyBatis 中传多个参数的方式,顺带结合源码看看 MyBatis 的底层是怎么处理这些参数的。

面试官问的“多个参数”到底是哪种情况?

先回顾一下背景。在 MyBatis 中,我们通常会写一个 Mapper 接口,比如这样:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_XML

问题就来了:MyBatis 的 XML 映射文件里,只能通过 #{} 或 ${} 获取参数,而方法参数是多个,怎么取?

这就是我们今天要深入的点。

使用 @Param 注解

这是最标准、最推荐的方式!MyBatis 提供了 @Param 注解,可以为每个参数起一个别名。

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_方法参数_02

对应 XML 中就能这样写:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_封装_03

这个时候,MyBatis 内部会把所有的参数封装成一个 Map<String, Object>,你定义了 @Param("xxx"),Map 里就会有对应的键值对,方便取值。

优点:

  • 清晰明了
  • 对应 XML 一目了然
  • 不容易出错

注意:如果用的是 Spring + Mapper 接口(不写 XML),配合注解 SQL 时也推荐用 @Param。

使用 Map 传参(适合参数动态、数量不固定)

这个方式我在项目里常用,比如查询条件很多,有时候我就干脆传个 Map:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_封装_04

XML 里可以这样取:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_方法参数_05

优点:

  • 灵活,应对复杂条件查询
  • 动态 SQL 编写非常方便

缺点:

  • 缺乏类型约束,IDE 无法提示键名拼写错误
  • 可读性略差,尤其参数多时

使用 JavaBean 或 DTO 对象传参

这个适用于场景固定、字段比较多时,比如分页查询时统一传一个 QueryDTO:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_方法参数_06

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_方法参数_07

XML 中直接用 #{name}、#{age} 即可,MyBatis 会通过反射拿字段值。

优点:

  • 类型安全、结构清晰
  • 可拓展性强

缺点:

  • 如果只查一个字段反而略显臃肿

不加 @Param 的多个参数怎么处理?

这个就是面试官的“陷阱题”了!

如果你在 Mapper 方法里直接写多个参数但不加 @Param

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_XML_08

MyBatis 会自动封装成一个 ParamMap,并用 param1, param2, ... paramN 做 key,也就是:

  • param1 → name
  • param2 → age

所以 XML 里你只能写:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_XML_09

你写 #{name} 是取不到值的!

所以,不写 @Param 也能用,只是你得知道 MyBatis 默认的命名机制。

MyBatis 是如何封装多个参数的?

这是我写完 demo 后去翻源码才发现的“真相”!

MyBatis 最终会把你传入的方法参数,统一转换成一个 ParamMap(继承自 HashMap),你可以理解为:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_方法参数_10

当你用了 @Param("name"),它会往 map 里放:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_XML_11

如果你没用 @Param,它会用默认名字:、

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_封装_12

而这个 map 就是你在 XML 里的 #{} 对象来源!

面试官为什么这么爱问这个问题?

因为它既考察你的基础,又考察你对 MyBatis 源码的理解。

尤其是在大厂社招,很多项目都用 MyBatis + SpringBoot,而参数传递正是常踩的坑!

举个例子:你同事没加 @Param,结果你写了 #{userId} 就报错了,可能花半小时才找出是应该写 #{param1}……

这类 bug 不难,但一出问题就很低级,容易让人怀疑你对 MyBatis 的熟练度。

项目实战中的使用建议

最后总结一下我在项目中的使用经验:

MyBatis传参原来还有这么多门道,90%程序员都只知道一种!_封装_13

尾声:面试不怕问,就怕懵

说到底,MyBatis 的多个参数传递不复杂,但细节很多。

从 @Param 到默认 param1 命名,从 Map 到 Bean,其实都是为了让你在 XML 中能准确无误地引用参数。

那次面试之后我深有体会:

“看起来很基础的题,背后往往藏着功力。”

所以,如果你也在准备面试,不妨把这几个参数传递方式都敲一遍,再翻一翻源码,会让你对 MyBatis 的理解更上一层楼。

下次遇到“如何传多个参数”这个问题,你就可以微笑着反问一句:

“您是想听注解方式,还是源码解析?”

END

如果你觉得这篇文章对你有帮助,欢迎【点赞】【转发】【在看】,支持我这个努力写作的程序员小米~

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!

我们下次技术分享,再见!