mybatis高频面试题

什么是mybatis

  • mybatis框架是一个开源的数据持久性层框架
  • 它的内部封装了通过JDBC访问数据库的操作,支持普通的SQL查询、存储过程和高级映射,几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索。
  • MyBatis作为持久层框架,其主要思想是将程序中的大量SQL语句剥离出来,配置在配置文件当中,实现SQL的灵活配置。
  • 这样做的好处是将SQL与程序代码分离,可以在不修改代码的情况下,直接在配置文件当中修改SQL。

什么是ORM

ORM(Object Relational Mapping),对象关系映射是一种为了解决关系型数据库数据与简单Java对象(POJO)的映射关系的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。

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

Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。

而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。

MyBatis框架的优缺点及其适用的场景

优点:

  • 与JDBC相比,减少了50%以上的代码量。
  • MyBatis是易学的持久层框架,小巧并且简单易学。
  • MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML文件里,从程序代码中彻底分离,降低耦合度,便于统一的管理和优化,并可重用。
  • 提供XML标签,支持编写动态的SQL,满足不同的业务需求。
  • 提供映射标签,支持对象与数据库的ORM字段关系映射。
    缺点:
  • SQL语句的编写工作量较大,对开发人员编写SQL的能力有一定的要求。
  • SQL语句依赖于数据库,导致数据库不具有好的移植性,不可以随便更换数据库。

mybatis工作原理

图解
在这里插入图片描述
执行流程

  1. 读取mybatis配置文件:mybatis-config.xml(加载运行环境和配置文件)
  2. 构造会话工厂SqlSessionFactory
  3. SqlSessionFactory创建SqlSession对象(包含了执行SQL语句的所有方法)
  4. Executor执行器(操作数据库的接口),同时负责查询缓存的维护
  5. Executor接口的执行方法中有一个MappedStatement类型的参数,里面封装了映射信息
  6. 输入参数映射
  7. 输出结果映射

mybatis是否支持延迟加载

什么是延迟加载
在这里插入图片描述
结论:mybatis是支持延迟加载的,但默认是不开启

在mybatis-config.xml开启全局延迟加载配置

<setting name="lazyLoadingEnabled" value="true"/>

延迟加载配置

#开启懒加载
mybatis.configuration.lazy-loading-enabled=true

在mybatis中,一对一关联的 association 和一对多的collection可以实现懒加载(fetchType属性)。resultMap可以实现高级映射,所以Mybatis在实现懒加载时要使用 resultMap,不能使用 resultType。
开启局部延迟加载配置

<collection fetchType="lazy"/>
<association fetchType="lazy"/>

延迟加载的原理

在这里插入图片描述

  1. 使用CGLIB创建目标对象的代理对象
  2. 当调用目标方法user.getOrderList方法时,进入拦截器invoke方法,若user.getOrderList方法为null时,执行sql查询order列表
  3. 查询到order列表,然后去调用user.setOrderList方法给orderList属性赋值,最后完成了user.getOrderList方法的调用

一二级缓存

一级缓存:基于PerpetualCache的HashMap本地缓存,作用域为Session。当Session进行flush或close后,该Session中的所有缓存将被清除。一级缓存默认是开启的。

二级缓存:也是基于PerpetualCache的HashMap本地缓存,作用域为namespace和mapper的作用域,不依赖于sql session。

二级缓存配置:默认是关闭的,需要在Mybatis的配置文件中配置

<settings>
    <setting name="cacheEnabled" value="true"/> <!--Mybatis的二级缓存配置-->
</settings>

然后在mapper中添加cache标签

<mapper namespace="com.snow.xml.SnowOracle">
    <cache></cache> <!--Mybatis的二级缓存配置-->
</mapper>

二级缓存注意事项

  • 对于缓存数据更新机制,当某个作用域(一级缓存(session)、二级缓存(namespace)的数据进行了增删查操作后,默认该作用域下的所有select中的缓存将被清除)
  • 二级缓存需要缓存的数据需要实现serializable接口
  • 只有会话提交或会话关闭后,一级缓存中的数据才会转移到二级缓存中

Mybatis 中的一级缓存与二级缓存

# 和${}的区别

  • #{}是预编译处理,${}是字符串替换
  • 处理#{}时,会将sql中的#{}整体替换为占位符(即:?),调用PreparedStatement的set方法来赋值;
  • 在处理 $ { } 时,就是把 ${ } 替换成变量的值。

#示例
#{ } 被解析成预编译语句,预编译之后可以直接执行,不需要重新编译sql。

//sqlMap 中如下的 sql 语句
select * from user where name = #{name};
//解析成为预编译语句;编译好SQL语句再取值
select * from user where name = ?;

$ {}示例
${ } 仅仅为一个字符串替换,每次执行sql之前需要进行编译,存在 sql 注入问题。

select * from user where name = '${name}'
//传递的参数为 "ruhua" 时,解析为如下,然后发送数据库服务器进行编译。取值以后再去编译SQL语句。
select * from user where name = "ruhua";

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

预编译是提前对SQL语句进行预编译,而后再调用SQL,注入的参数就不会再进行SQL编译。而SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译时SQL时轻而易举的通过,从而导致数据泄露。而预编译机制则可以很好的防止SQL注入。

更多的mybatis面试题

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值