作者 | 浩说编程
来源 | 公众号:浩说编程
[ 大厂技术资源 | 研发必备安装包 | 经典必读电子书 | 限时免费获取 ]
问题导读
一、了解MyBatis的一级缓存、二级缓存吗?
追问-1:如何配置二级缓存?
追问-2:一级缓存和二级缓存的使用顺序?
二、MyBatis的分页原理是什么?
三、MyBatis如何实现一对多复杂查询?
一、了解MyBatis的一级缓存、二级缓存吗?
正经回答:
先说缓存,合理使用缓存是系统优化的常见手段。
将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询。
而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力。
同时提高系统性能。
一级缓存
一级缓存是SqlSession级别的缓存。
在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。
不同的sqlSession之间的缓存数据区域是互相不影响的。
也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。
一级缓存的工作原理:
与Redis同理,用户发起查询请求,查找某条数据,sqlSession先去缓存中查找,是否有该数据。
如果有,直接返回;如果没有,从数据库中查询,并将查询到的数据放入一级缓存区域,供下次查找使用。
但sqlSession执行commit,即增删改操作时会清空缓存。这么做的目的是避免脏读。
码文不易
你的关注是浩说编程持续更新的动力
浩说编程会做的更好
二级缓存
为什么要有二级缓存?
二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存。
二级缓存是跨SqlSession的。二级缓存的作用范围更大。
在实际开发中,MyBatis通常和Spring进行整合开发。
Spring将事务放到Service中管理,对于每一个service中的sqlsession是不同的。
这是通过mybatis-spring中的
org.mybatis.spring.mapper.MapperScannerConfigurer创建sqlsession自动注入到service中的。
每次查询之后都要进行关闭sqlSession,关闭之后数据即被清空。
所以spring整合之后,如果没有事务,一级缓存是没有意义的。
深入追问:
追问-1:如何配置二级缓存?
MyBatis对二级缓存的支持粒度很细,它会指定某一条查询语句是否使用二级缓存。
1、MyBatis支持二级缓存的总开关,全局配置变量cacheEnabled=true
在mybatis-config.xml添加
<settings>
<setting name="cacheEnabled" value="true"/><!-- 二级缓存 -->
</settings>
2、该select语句所在的Mapper,配置 或节点
<mapper namespace="com.xxxx.dao.TaskDao">
<cache/>
<insert id="addxxx" parameterType="xxx" >
insert into xxx (name, price) values (#{name}, #{price})
</insert>
<select id="listXXX" resultType="xxx">
select * from xxx
</select>
</mapper>
3、该select语句的参数 useCache=true
<select id="selectXXXX" resultMap="task" parameterType="java.util.Map" useCache="true">
追问-2:一级缓存和二级缓存的使用顺序?
MyBatis查询数据的顺序是:
二级缓存 👉 一级缓存 👉 数据库
二、MyBatis的分页原理是什么?
正经回答:
Mybatis使用RowBounds对象进行分页
它是针对ResultSet结果集执行的内存分页,而非物理分页。
可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理
使用Mybatis提供的插件接口,实现自定义插件。
在插件的拦截方法内拦截待执行的sql,然后重写sql。
根据dialect方言,添加对应的物理分页语句和物理分页参数。
拦截过程举例:
select * from student;
拦截sql后重写为:
select t.* from (select * from student) t limit 0, 10
三、MyBatis如何实现一对多复杂查询?
场景举例:
比如一个用户存在多个订单(一对多关系),那么如何通过MyBatis一次查询出用户以及用户下包含的订单集合?
正经回答:
可以使用联合查询语句,只查询一次,
然后通过使用resultMap里面的association,collection节点配置一对多的类就可以完成。
使用举例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kerwin.mybatis.pojo.Person">
<resultMap type="com.kerwin.mybatis.pojo.Person" id="personreSultMap">
<id column="p_id" property="id"/>
<result column="name" property="name"/>
<collection property="orderList" ofType="com.kerwin.mybatis.pojo.Orders" column="pid">
<id column="o_id" property="id"/>
<result column="price" property="price"/>
</collection>
</resultMap>
<select id="selectPersonFetchOrder" parameterType="int" resultMap="personreSultMap" >
select p.*,o.* from person p,orders o where o.pid=p.p_id and p.p_id=#{id}
</select>
</mapper>
===
每日小结
今天我们复习了面试中常考的MyBatis三个问题,你做到心中有数了么?
对了,**如果你的朋友也在准备面试,请将这个系列扔给他,如果他认真对待,肯定会感谢你的!!**
好了,今天就到这里,学废了的同学,记得三连,也会给我继续更新的动力。
作者 | 浩说编程
来源 | 公众号:浩说编程
[ 大厂技术资源 | 研发必备安装包 | 经典必读电子书 | 限时免费获取 ]