2020 12 28 Mybatis面试题

在这里插入图片描述

Mybatis 面试题

1、Mybatis的工作原理

在这里插入图片描述

  1. 读取Mybatis配置文件:mybatis-config.xml为Mybatis的全局配置文件,配置了Mybatis的运行环境等信息,例如数据库链接信息。
  2. 加载映射文件。映射文件即SQL映射为文件,该文件中配置了操作数据库的SQL语句,需要再Mybatis配置文件mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。
  3. 构造会话工厂:通过Mybatis的环境等配置信息构建会话工厂SqlSessionFactory
  4. 创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法
  5. Executor执行器:Mybatis底层定义了一个Executor接口来操作数据库,他根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护
  6. MappedStatment对象:在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用域存储要映射的SQL语句的id,参数等信息。
  7. 输入参数映射:输入参数类型可以是Map,List等集合类型,也可以是基本数据类型和POJO类型。输入结果映射过程类似与JDBC对preparedStatement对象设置参数的过程
  8. 输出结果映射:输出结果类型可以是Map,List等集合类型,也可以是基本数据类型和POJO类型,输出结果映射过程类型与JDBC对结果集的解析过程

2、Mybatis 缓存

Mybatis中有一级缓存和二级缓存,默认情况下一级缓存是开启的,而且是不能关闭的

一级缓存是指 SqlSession 级别的缓存,当在同一个 SqlSession 中进行相同的 SQL 语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存 1024 条 SQL。

二级缓存是指可以跨 SqlSession 的缓存。是 mapper 级别的缓存,对于mapper 级别的缓存不同的sqlsession 是可以共享的。
在这里插入图片描述

3、Mybatis的一级缓存原理(SqlSession级别)

第一次发出一个查询Sql ,sql查询结果写入sqlsession 的一级缓存中,缓存使用的数据结构是一个map

key:MapperID+offset+limit+Sql+所有的入参value:用户信息

同一个sqlsession再次发出相同的sql,就从缓存中取出数据。如果两次之间出现commit操作(修改,添加,删除),本sqlsession中的一级缓存区域全部清空,下次再去缓存中查询不到所以要从数据库查询,从数据库查询到再写入缓存。

4、二级缓存原理(mapper级别)

二级缓存的范围是mapper级别(mapper同一个命名空间按,Namespace),mapper以命名空间为单位创建缓存数据结构,结构是map。mybatis的二级缓存是通过CacheExecutor实现的。CacheExecutor其实是Executor的代理对象。所有的查询操作,在CacheExecutor中都会先匹配缓存中是否存在,不存在则查询数据库。

key:MapperID+offset+limit+Sql+所有的入参

具体使用需要配置:

  1. Mybatis全局配置中启用二级缓存配置
  2. 在对应的Mapper.xml中配置cache节点
  3. 在对应的select查询节点中添加userCache=true

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

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

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

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

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

预编译语句的优势在于归纳 为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止sql注入。

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

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

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

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

7、Mybatis是如何将Sql执行结果封装为目标对象并返回的?都有哪些映射形式?

  • 第一种是使用标签,逐一定义列名和对象属性名之间的映射关系。
  • 第二种是使用sql列的别名功能,将列别名书写为对象属性名,比如T_NAME AS NAME,对象属性名一般是name,小写,但是列名不区分大小写,Mybatis会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis一样可以正常工作。

有了列名与属性名的映射关系后,Mybatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

8、Mybatis一对一、一对多的查询

MyBatis 中使用collection标签来解决一对多的关联查询,collection标签可用的属性如下: property:指的是集合属性的值. ofType:指的是集合中元素的类型. column:所对应的外键字段名称. select:使用另一个查询封装的结果.

MyBatis 中使用association标签来解决一对一的关联查询,association标签可用的属性如下: property:对象属性的名称. javaType:对象属性的类型. column:所对应的外键字段名称. select:使用另一个查询封装的结果!

如:

<mapper namespace="com.lcb.mapping.userMapper"><!--collection  一对多关联查询 -->  
    <select id="getClass2" parameterType="int" resultMap="ClassesResultMap2">  
        select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}  
    </select>  
    <resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">  
        <id property="id" column="c_id"/>  
        <result property="name" column="c_name"/>  
        <association property="teacher" javaType="com.lcb.user.Teacher">  
            <id property="id" column="t_id"/>  
            <result property="name" column="t_name"/>  
        </association>  
        <collection property="student" ofType="com.lcb.user.Student">  
            <id property="id" column="s_id"/>  
            <result property="name" column="s_name"/>  
        </collection>  
    </resultMap>  
    
    <!--association  一对一关联查询 -->  
    <select id="getClass" parameterType="int" resultMap="ClassesResultMap">  
        select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}  
    </select>  
    <resultMap type="com.lcb.user.Classes" id="ClassesResultMap">  
        <!-- 实体类的字段名和数据表的字段名映射 -->  
        <id property="id" column="c_id"/>  
        <result property="name" column="c_name"/>  
        <association property="teacher" javaType="com.lcb.user.Teacher">  
            <id property="id" column="t_id"/>  
            <result property="name" column="t_name"/>  
        </association>  
    </resultMap>  
</mapper>  
        
 <!-- 参考自:https://www.cnblogs.com/xdp-gacl/p/4264440.html -->  

个人觉得,发送一个Sql去查询,使用List 作为回参也可以做到

上面这段代码,也是面试经常问道的将Sql执行结果封装为目标对象并返回,其实现的过程就是通过resultMap 进行封装,而property 和column进行映射,使数据库的列名和对象的名称对应。Mybatis也会智能匹配,比如可以指定驼峰,如果找不到映射对应的关系,就是默认值。

9、Mybatis的分页原理

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

分页插件的原理就是使用Mybatis提供的插件接口,实现自定义差价,在插件的拦截方法内,拦截待执行的SQL,然后根据设置的dialect,和设置的分页参数,重写SQL,生成带有分页语句的SQL,执行重写后的SQL,从而实现分页。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10

10、什么是Mybatis的动态SQL?

  1. 传统的JDBC的方法,在组合SQL语句的时候需要去拼接,稍微不注意就会少了一个空格,标点符号,都会导致系统错误。Mybatis的动态SQL就是为了解决这种问题而产生的;Mybatis的动态SQL语句值基于OGNL表达式的,方便再SQL语句中实现某些逻辑;可以使用标签组合成灵活的sql语句,提供开发的效率;
  2. Mybatis的动态SQL标签主要由以下几类:If语句(简单的条件判断)
    Choose(when/otherwise),相当于java语言中的switch,与jstl中choose类似 Trim(对包含的内容加上prefix,或者suffix) Where(主要是用来简化SQL语句中where条件判断,能智能的处理and/or 不用担心多余的语法导致的错误) Set(主要用于更新时候) Foreach(一般使用在mybatis in语句查询时特别有用)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值