mybatis十六问

mybatis面试专题

文章目录

1.讲下 MyBatis 的缓存
一级缓存:一级缓存是session级别的缓存,指的是创建一个session,从数据库中查询数据,数据会自动保存到session中,下次查询就直接从session中取,不同session之间是互不影响的并且是默认开启的。
一级缓存应用:springboot中使用mybatis中的一级缓存,在service层多次对mapper接口调用查询数据时,此时需要开启事务,使用一级缓存,来提高性能,查询效率。如果不开始事务,在spingboot中每次调用mapper接口都会创建新session,缓存就会失效,因为是不同session。
二级缓存:二级缓存是mapper级别的缓存,指的是不同session之间查询数据,也能缓存数据,可以说是namespace下的session是对缓存起作用的。
开启二级缓存

mybatis.configuration.cache-enabled=true

开启缓存之后,还需要在mapper文件中可以指定一个namespace下加上标签

<mapper namespace="com.secbro.mapper.OrderMapper" >
<cache/>
<!--省略其他内容-->
</mapper>

二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口。如果存在父类、成员pojo都需要实现序列化接口。否则,执行的过程中会直接报错。

2.Mybatis 是如何进行分页的?
1.使用rowbounds对象进行分页,rowbounds对象分页实际上是逻辑分页,也就是在数据库中符合条件中的所有值都取出来,再进行分页。
2.sql语句使用limit
3.使用分页插件PageHelper,需要配置maven依赖,并在核心配置文件中配置分页插件拦截器,然后只需要在调用接口查询数据前使用PageHelper.startPage()方法,就能自动分页

3.Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
1.Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑
判断和动态拼接 sql 的功能
2.Mybatis 提供了 9 种动态 sql 标签:

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

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

4.#{}和¥{}的区别是什么?
1.#{}是预编译处理,¥{}是字符串替换。
2.Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法
来赋值,会对一些敏感字符进行过滤,编译过后会对传递的值加上双引号
3.Mybatis 在处理 时 , 就 是 把 {}时,就是把 {}替换成变量的值。
4.使用#{}可以有效的防止 SQL 注入,提高系统安全性。

5.Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
延迟加载就是按需加载,在需要查询的时候再去查询,使用延迟加载可以避免表连接查询,表连接查询比单表查询的效率低,关于延迟加载有两个重要的设置:lazyLoadingEnabled表示延迟加载是否开启,如果设置为true表示开启,此时还需要设置aggressiveLazyLoading为false,才能做到按需加载。比如说图书和类型两个表,有一个需求就是查看类型展示类型,点击类型在展示该类型的图书,此时可以用延迟加载,分别是写了两个sql去对应查询,使用collection来连接,当使用到图书类型时,才会去执行sql。
1.Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association
指的就是一对一,collection 指的就是一对多查询。
2.它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方
法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单
独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的
对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原

6.简述 Mybatis 的 Xml 映射文件和 Mybatis 内部数据结构之间的映射关系?
Mybatis 将所有 Xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。在
Xml 映射文件中,标签会被解析为 ParameterMap 对象,其每个子元素会
被解析为 ParameterMapping 对象。标签会被解析为 ResultMap 对象,其每个子
元素会被解析为 ResultMapping 对象。每一个、、、标签
均会被解析为 MappedStatement 对象,标签内的 sql 会被解析为 BoundSql 对象。

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

7.MyBatis 实现一对一有几种方式?具体怎么操作的?
联合查询和嵌套查询
联合查询就是联表查询,如下:

<select id="getstudent2" resultMap="studentteacher2">
    select a.id aid,a.name aname,b.name bname
    from student a,teacher b
    where a.tid=b.id
</select>
<resultMap id="studentteacher2" type="student">
    <result property="id" column="aid"/>
    <result property="name" column="aname"/>
    <association property="teacher" javaType="teacher">---(这里不用tid)
        <result property="name" column="bname"/>
    </association>
</resultMap>

嵌套查询就是子查询,如下:

---通过学生的tid去寻找对应的老师
<select id="getstudent" resultMap="studentteacher">(结果集映射)
     select *from student
 </select>
<resultMap id="studentteacher" type="student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="teacher" column="tid" javaType="teacher" select="getteacher"/>
    --(对象用association)
</resultMap>
<select id="getteacher" resultType="teacher">
    select *from teacher where id=#{id}  ----(只有一个老师时,不要这个where条件,不会报错,当有多个老师,就会报错:Statement returned more than one row, where no more than one was expected.)
</select>

8.MyBatis 里面的动态 Sql 是怎么设定的?用什么语法?
MyBatis 里面的动态 Sql 一般是通过 if 节点来实现,通过 OGNL 语法来实现,但是如果要
写的完整,必须配合 where,trim 节点,where 节点是判断包含节点有内容就插入 where,否则不
插入,trim 节点是用来判断如果动态语句是以 and 或 or 开始,那么会自动把这个 and 或者 or
取掉。

9.Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式?
第一种是使用标签,第二种是使用 sql 列的别名功能,有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。

10.Mybatis 映射文件中,如果 A 标签通过 include 引用了 B 标签的内容,请问,B 标签能否定义在 A 标签的后面,还是说必须定义在 A 标签的前面?
sql标签可以是用来抽取公共的sql片段放在sql标签中,用include标签来使用这个sql片段。
虽然 Mybatis 解析 Xml 映射文件是按照顺序解析的,但是,被引用的 B 标签依然可以
定义在任何地方,Mybatis 都可以正确识别。原理是,Mybatis 解析 A 标签,发现 A 标签引
用了 B 标签,但是 B 标签尚未解析到,尚不存在,此时,Mybatis 会将 A 标签标记为未解
析状态,然后继续解析余下的标签,包含 B 标签,待所有标签解析完毕,Mybatis 会重新
解析那些被标记为未解析的标签,此时再解析 A 标签时,B 标签已经存在,A 标签也就可
以正常解析完成了。

11.Mybatis 中如何执行批处理?
批处理即批量处理。如果需要往数据库中插入大量数据时,再使用单条插入即插入一次调一次insert语句就会很浪费资源。所以针对于批量数据新增、删除、修改、查找的操作,mybatis提供了批处理方案。
1.使用foreach标签进行批处理,当数据量很大时,插入需要耗时也是非常的长的,因为sql语句有着非常多的占位符。
2.使用 BatchExecutor 完成批处理,如下:
在这里插入图片描述

12.Mybatis 都有哪些 Executor 执行器?它们之间的区别是什么?
Mybatis 有三种基本的 Executor 执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
1)SimpleExecutor:每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭 Statement 对象。
2)ReuseExecutor:执行 update 或 select,以 sql 作为key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象,而是放置于 Map
3)BatchExecutor:完成批处理。

13.Mybatis 中如何指定使用哪一种 Executor 执行器?
在 Mybatis 配 置文件中, 在设置 ( settings) 可以指定默认 ExecutorType 执 行器类型

14.Mybatis 执行批量插入,能返回数据库主键列表吗?
在插入批量插入的statement配置一下useGeneratedKeys和keyProperty这两个配置,当插入成功之后,就可以在list的所有对象的id属性上看到返回的id值
在这里插入图片描述

15.Mybatis 是否可以映射 Enum 枚举类?
Mybatis 可以映射枚举类,不单可以映射枚举类,Mybatis 可以映射任何对象到表的一
列上。映射方式为自定义一个 TypeHandler,实现 TypeHandler 的 setParameter()和
getResult()接口方法。TypeHandler 有两个作用,一是完成从 javaType 至 jdbcType 的转换,
二是完成 jdbcType 至 javaType 的转换,体现为 setParameter()和 getResult()两个方法,分别
代表设置 sql 问号占位符参数和获取列查询结果。

16.使用 MyBatis 的 mapper 接口调用时有哪些要求?
1)Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同
2)Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同
3)Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同
4)Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值