Mybatis面试题整理

本文详细介绍了MyBatis的面试常见问题,包括MyBatis的简介、优点、缺点,以及ORM概念。讨论了MyBatis作为半自动ORM工具与全自动ORM的区别,并概述了MyBatis的编程步骤。此外,还解释了#和$的区别,一级缓存与二级缓存的工作原理,分页查询方式,动态SQL的使用,以及关联查询的支持。最后,提到了MyBatis的延迟加载机制及其实现原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Mybatis面试题

1. 谈谈 MyBatis

Mybatis 是一个半自动化的 ORM 框架,它对 jdbc 的操作数据库的过程进行封装,使得开发者只需要专注于 SQL 语句本身,而不用去关心注册驱动,创建 connection 等,Mybatis 通过 xml文件配置或者注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中的sql 进行映射成最终执行的 sql 语句,最后由 Mybatis 框架执行 sql 并将结果映射成 java 对象并返回。每个 MyBatis 应用程序主要都是使用 SqlSessionFactory 实例的,一个 SqlSessionFactory 实例可以通过 SqlSessionFactoryBuilder 获得。SqlSessionFactoryBuilder 可以从一个 xml 配置文件或者一个预定义的配置类的实例获得。
Mybatis 分为三层
(1)API 接口层:提供给外部使用的接口 API
(2)数据处理层:负责具体的 SQL
(3)基础支撑层:负责最基础的功能支撑,如连接管理,事务管理,配置加载和缓存处理。

2. Mybatis 的优点

(1) 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并可重用。
(2)与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;
(3)很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持)。
(4)能够与 Spring 很好的集成;
(5)提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

3. Mybatis 的缺点
  • Sql 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写 Sql 语句的功底有一定要求。
  • 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择。
4. 什么是 ORM

对象关系映射(Object Relational Mapping,简称 ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。常见的 ORM 框架有:Hibernate、TopLink、Castor JDO、Apache OJB、MyBatis 等。

5. 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?

Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。

6. Mybatis 的编程步骤是什么样的?
  • 创建 SqlSessionFactory
  • 通过 SqlSessionFactory 创建 SqlSession
  • 通过 sqlsession 执行数据库操作
  • 调用 session.commit()提交事务
  • 调用 session.close()关闭会话
7. Mybatis 中#和$的区别?
  • ${}是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,如:order by #user_id#,如果传入的值是 111,那么解析成 sql 时的值为 order by “111”, 如果传入的值是 id,则解析成的 sql 为 order by “id”
  • #{}是 sql 的参数占位符,Mybatis 会将 sql 中的#{}替换为?号,在 sql 执行前会使用PreparedStatement 的参数设置方法,按序给 sql 的?号占位符设置参数值。比如 ps.setInt(0, parameterValue),#{item.name}的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 param.getItem().getName()。
  • #方式能够很大程度防止 sql 注入。
  • $方式无法防止 Sql 注入。
  • $方式一般用于传入数据库对象,例如传入表名。
  • 一般能用#的就别用$。
8.Mybatis 中一级缓存与二级缓存?
  • 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空。

  • 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。作用域为namespance 是指对该 namespance 对应的配置文件中所有的 select 操作结果都缓存,这样不同线程之间就可以共用二级缓存。

    启动二级缓存:在 mapper 配置文件中:。二级缓存可以设置返回的缓存对象策略:。当 readOnly="true"时,表示二级缓存返回给所有调用者同一个缓存对象实例,调用者可以 update 获取的缓存实例,但是这样可能会造成其他调用者出现数据不一致的情况(因为所有调用者调用的是同一个实例)。当 readOnly="false"时,返回给调用者的是二级缓存总缓存对象的拷贝,即不同调用者获取的是缓存对象不同的实例,这样调用者对各自的缓存对象的修改不会影响到其他的调用者,即是安全的,所以默认是 readOnly=“false”;3. 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存 Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

9. Mybatis 是如何迚行分页的?分页插件的原理是什么?
  • Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页,可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
  • 分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。
  • 举例:select * from student,拦截 sql 后重写为:select t.* from (select * from student)t limit
    0,10
10. Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
  • Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和 动 态 拼 接 sql 的 功 能 , Mybatis 提供了 9 种动态 sql 标 签
    trim|where|set|foreach|if|choose|when|otherwise|bind。
  • 其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接
    sql,以此来完成动态 sql 的功能。
11. Mybatis 能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别。
  • 能,Mybatis 不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询,多对一查询,其实就是一对一查询,只需要把 selectOne()修改为 selectList()即可;多对多查询,其实就是一对多查询,只需要把selectOne()修改为 selectList()即可。
  • 关联对象查询,有两种实现方式,一种是单独发送一个 sql 去查询关联对象,赋给主对象,然后返回主对象。另一种是使用嵌套查询,嵌套查询的含义为使用 join 查询,一部分列是 A 对象的属性值,另外一部分列是关联对象 B 的属性值,好处是只发一个 sql 查询,就可以把主对象和其关联对象查出来。
12.Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
  • Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。
  • 它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
  • 当然了,不光是 Mybatis,几乎所有的包括 Hibernate,支持延迟加载的原理都是一样的。

未完待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值