写点什么

MyBatis 面试题(部分)

作者:andy
  • 2022-10-27
    北京
  • 本文字数:1350 字

    阅读完需:约 4 分钟

一、MyBatis 和 Ibatis 区别


1、Mybatis 实现了接口绑定,使用更加方便。

在 ibatis2.x 中我们需要在 DAO 的实现类中指定具体对应哪个 xml 映射文件,而 Mybatis 实现了 DAO 接口与 xml 映射文件的绑定,自动为我们生成接口的具体实现,使用时不需要通过 SqlMapClient 去指定 namespace 和 sql statement id, 只需要在 sql map config 文件中指定接口的 namespace, 并且 sql statement id 和 接口的名字意义对应,然后调用对一个接口即可。

注意:

虽然 Mybatis 支持在接口中直接使用 annotation 的配置方式来简化配置,不过强烈建议仍然使用 xml 配置的方式。毕竟 annotation 的配置方式功能有限且代码入侵性太强。使用 xml 配置方式才能体现出 Mybatis 的优势所在。

2、对象关系映射的改进,效率更高。

相信很多在使用 ibatis2.x 的朋友并没有通过 ibatis 的 xml 映射文件来实现对象间的关系映射。其实也确实没有必要那么做,因为 ibatis2.x 采用的是“嵌套查询”的方式将对象之间的关系通过查询语句的直接拼装来实现,其效果和在 DAO 或 Service 中自行封装是一样的。

不过这种方式存在“N+1 查询问题”。

概括地讲,N+1 查询问题可以是这样引起的:

? 你执行了一个单独的 SQL 语句来获取结果列表(就是+1)。

? 对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是 N)。

这个问题会导致成百上千的 SQL 语句被执行。这通常不是期望的。

而在 Mybatis 中,除了兼容 ibatis2.x 中的“嵌套查询”方式外,还提供了直接“嵌套结果”的方式,其效果相当于直接通过一句 sql 将查询出的 dto 对象自动封装成所需的对象。

不过实际上这一改进所带来的好处也是很有限的。因为这一方式在使用分页的时候并不起作用,或者说嵌套对象的结果集是不允许进行分页的。这一点在 Mybatis 框架中已经做出了明确的限制(org.apache.ibatis.executor.resultset.NestedResultSetHandler 里 34 行),而实际项目中需要分页的情况又特别多……

仔细一想,一对多映射确实不能通过配置文件来分页,因为这时查询出的记录数并不等于实际返回对象的 size,不过一对一映射为什么也不允许就不太明白了。可能是因为一对一是一对多的特例,而在设计框架的时候并没有考虑去处理或是难于处理这一特例吧。

3、MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

熟悉 struts2 的人应该对 OGNL 表达式不会感到陌生,MyBatis 采用 OGNL 表达式简化了配置文件的复杂性,使用起来更简洁。

补充:比较遗憾的是,Mybatis 的分页继续沿用 ibatis2.x 的逻辑分页方式,依赖于 JDBC 的规范。大数据量时会出现性能问题,要想实现物理分页还得自己想办法改了。


二、#{}和 ${}的区别是什么?


#{}是预编译处理,${}是字符串替换。

使用 #{}可以有效的防止 SQL 注入,提高系统安全性。

Mybatis 在处理 #{}时,会将 sql 中的 #{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;

Mybatis 在处理 ${}时,就是把 ${}替换成变量的值。


三、Mybatis 是如何进行分页的?分页插件的原理是什么?


Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页,可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。

用户头像

andy

关注

还未添加个人签名 2019-11-21 加入

还未添加个人简介

评论

发布
暂无评论
MyBatis面试题(部分)_andy_InfoQ写作社区