Mybatis框架面试典籍30+ | 大别山码将

Mybatis

什么是MyBatis?优缺点及适用场景

Mybatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作, 开发时只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动.创建连接.创 建 statement 等繁杂的过程。程序员直接编写原生态 sql,可以严格控制 sql执 行性能,灵活度高。

MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映 射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取 结果集。

通过 xml 文件或注解的方式将要执行的各种 statement 配置起来, 并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回(从执 行 sql 到返回 result 的过程)。

优点:

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。

  • 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设 计造成任何影响;SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管 理;提供 XML 标签,支持编写动态 SQL 语句,并可重用。

  • 与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的 代码,不需要手动开关连接;

  • 很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库, 所以只要 JDBC 支持的数据库 MyBatis 都支持)。

  • 能够与 Spring 很好的集成;

  • 提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象 关系映射标签,支持对象关系组件维护

缺点:

  • 1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
  • 2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
  • 3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。

适用场景:

  • MyBatis 专注于 SQL 本身,是一个足够灵活的 DAO 层解决方案。
  • 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis 将是不错的选择

mybatis的一级缓存和二级缓存:

缓存的作用:使用缓存, 我们可以避免频繁的与数据库进行交互, 尤其是在查询越多、缓存命中率越高的情况下, 使用缓存对性能的提高更明显。mybatis 也提供了对缓存的支持, 分为一级缓存和二级缓存。 但是在默认的情况下, 只开启一级缓存

MyBatis与Hibernate有哪些不同

  • Mybatis 和 hibernate 不同,它不完全是一个ORM 框架,Mybatis 是一个半 ORM(对象关系映射)框架,因为 MyBatis需要程序员自己编写 Sql 语句。
  • Mybatis 直接编写原生态 SQL,可以严格控制 SQL 执行性能,灵活 度高,非常适合对关系数据模型要求不高的软件开发
  • Hibernate 对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件,如果用 Hibernate 开发可以节省很多代码,提高效率。

#{}和${}的区别

#{} 是 sql 的参数占位符,${}是 Properties ⽂件中的变量占位符

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

Mybatis 在处理 时 , 就 是 把 {}时,就是把 {}替换成变量的值。使 用#{}可以有效的防止 SQL 注入,提高系统安全性。

MyBatis是如何进行分页的?分页插件的原理是什么?

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

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

实现 Mybatis 的 Interceptor 接⼝并复写 intercept() ⽅法,然后在给插件编写注解,指定要拦截哪⼀个接⼝的哪些⽅法即可,记住,别忘了在配置⽂件中配置你编写的插件。

MyBatis的动态SQL

答:Mybatis 动态 sql 可以让我们在 Xml 映射⽂件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能,Mybatis 提供了 9 种动态 sql 标签

trim|where|set|foreach|if|choose|when|otherwise|bind 。

其执⾏原理为,使⽤ OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。

MyBatis是是如何将sql执行结果封装为目标对象并返回的?都有哪些映射方式?

第⼀种是使⽤ 标签,逐⼀定义列名和对象属性名之间的映射关系。

第⼆种是使用标签和 SQL 列的别名功能,将列的别名书写为 对象属性名。(⽐如 T_NAME AS NAME,对象属性名⼀般是 name,⼩写,但是列名不区分⼤⼩写,Mybatis 会忽略列名⼤⼩写,智能找到与之对应对象属性名),有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使⽤反射给对象的属性逐⼀赋值并返回,那些找不到映射关系的属性,是⽆法完成赋值的。

XML映射文件中,除了常见的select|insert|update|dalete标签之外,还有哪些标签

还有很多其他的标签, 、 、 、 、 ,加上动态 sql 的 9个标签, trim|where|set|foreach|if|choose|when|otherwise|bind 等,其中为 sql ⽚段标签,通过 标签引⼊ sql ⽚段, 为不⽀持⾃增的主键⽣成策略标签。

Mybatis的 Xml映射⽂件中,不同的Xml映射⽂件id是否可以重复?

不同的 Xml 映射⽂件,如果配置了 namespace,那么 id 可以重复;如果没有配置namespace,那么 id 不能重复;

原因就是 namespace+id 是作为 Map<String, MappedStatement> 的 key 使⽤的,如果没有namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,⾃然 id 就可以重复,namespace 不同,namespace+id ⾃然也就不同。

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

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

MyBatis能执行一对一,一对多的关联查询吗?都有哪些实现方式?

Mybatis 不仅可以执⾏⼀对⼀、⼀对多的关联查询,还可以执⾏多对⼀,多对多的关联查询,多对⼀查询,其实就是⼀对⼀查询,只需要把 selectOne() 修改为 selectList() 即可;多对多查询,其实就是⼀对多查询,只需要把 selectOne() 修改为 selectList() 即可。

通过关联对象查询,有两种实现⽅式,⼀种是单独发送⼀个 sql 去查询关联对象,赋给主对象,然后返回主对象。另⼀种是使⽤嵌套查询,嵌套查询的含义为使⽤ join 查询,先 查一个表,根据这个表里面的 结果的外键 id,去再另外一个表里面查询数据,也是 通过配置 collection,但另外一个表的查询通过 select 节点配置。

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,⽀持延迟加载的原理都是⼀样的。

Mybatis的一级缓存和二级缓存

1) 一级缓存: 一级缓存是SqlSession级别的缓存,默认开启,其存储作 用域为 Session。

它指的是Mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入到SqlSession为我们提供的一块区域中,该区域的结构是一个Map,当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,的话直接拿出来用,当SqlSession对象消失时,mybatis的一级缓存也就消失了,同时一级缓存是SqlSession范围的缓存,当调用SqlSession的修改、添加、删除、commit(),close等方法时,就会清空一级缓存。 不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。

实际开发中,MyBatis通常和Spring进行整合开发。Spring将事务放到Service中管理,对于每一个service中的sqlsession是不同的。所以spring整合之后,如果没有事务,一级缓存是没有意义的。

2) 二级缓存与一级缓存其机制相同,MyBatis的二级缓存是Application(mapper)级别的缓存,多个SqlSession可以共用二级缓存,它可以提高对数据库查询的效率,以提高应用的性能。默认不打开二级缓存,要手动开启二级缓存

他值得是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其缓存,但是其中缓存的是数据而不是对象,所以从二级缓存再次查询出得结果的对象与
第一次存入的对象是不一样的。

二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache, 当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

使用缓存是为了减少和数据库的交互次数,提高执行效率

什么是Mybatis的接口绑定?有哪些实现方式?

接口绑定,就是在 MyBatis 中任意定义接口,然后把接口里面的方法和 SQL 语句绑定, 我们直接调用接口方法就可以,这样比起原来了 SqlSession 提供的方 法我们可以有更加灵活的选择和设置。

接口绑定有两种实现方式:

  • 一种是通过注解绑定,就是在接口的方法上面加 上 @Select.@Update 等注解,里面包含 Sql 语句来绑定;
  • 另外一种就是通过 xml 里面写 SQL 来绑定, 在这种情况下,要指定xml 映射文件里面的 namespace 必须为接口的全路径名。当 Sql 语句比较简单时候,用注解绑定, 当 SQL 语句比 较复杂时候,用 xml 绑定,一般用 xml 绑定的比较多。

使用Mybatis的mapper接口调用时有哪些需求?

  • Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同;
  • Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的
  • parameterType 的类型相同;
  • Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的resultType 的类型相同;
  • Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。

简述Mybatis插件的运行原理,以及如何编写一个插件

插件是对系统默认功能的自定义修改,例如mybatis里面自定义插件,它实现的拦截器的功能。此类插件等同于拦截器。

我们知道,MyBatis有四大核心对象:

(1)ParameterHandler:处理SQL的参数对象
(2)ResultSetHandler:处理SQL的返回结果集
(3)StatementHandler:数据库的处理对象,用于执行SQL语句
(4)Executor:MyBatis的执行器,用于执行增删改查操作

那么,MyBatis拦截器针对的对象就是上面“四大金刚”。在Java里面,我们想拦截某个对象,只需要把这个对象包装一下,用代码行话来说,就是重新生成一个代理对象。一旦我们在mybatis-config.xml里面配置了插件,MyBatis四大核心对象(四大金刚)就会变身,变成代理对象

编写插件:实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然 后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在 配置文件中配置你编写的插件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李莲花*

多谢多谢,来自一名大学生的感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值