优秀的编程知识分享平台

网站首页 > 技术文章 正文

每日一练进击大厂「DAY13」Mybatis

nanyue 2024-11-21 18:55:30 技术文章 2 ℃

文章目录

  • 一、Mybatis的执行流程
  • 二、Mybatis中的执行器
  • 三、#{}和${}区别
  • 四、为什么需要预编译
  • 五、为什么调用dao接口的方法就能调用sql查询数据,原理是什么
  • 六、Mybatis的一级缓存和二级缓存
  • 七、Mybatis如何进行分页的
  • 八、Mybatis延迟加载的原理
  • 九、Mybatis的xml映射文件和Mybatis内部数据结构之间的映射关系
  • 总结

一、Mybatis的执行流程

  • 初始化工作解析配置文件,得到sqlSessionFactory,把配置文件中的参数都保存到configuration类中。解析mapper.xml文件,把每一个文件封装成一个MappedStatement,并且放入到Map。为每一个mapper接口类都会封装成一个MapperProxyFactory与namespace映射关系保存到map(key:namespace+sqlid value:MappedStatement)中。
  • 会话创建创建会话去执行sql,肯定是离不开sqlSession的。创建事务创建执行器,有三种执行器(会在下面的题中谈到)。返回defaultSqlSession对象。
  • 语句执行从knownMappers获取该接口的代理工厂类。使用JDK动态代理创建接口的代理类,MapperProxy为代理类,用于代理Mapper接口方法,调用mapper接口的方法都会到代理类MapperProxy的invoke方法。获取MappedStatement,这个在初始化的时候就知道存的是什么了,一个sql语句标签对应一个MappedStatement。通过执行器执行语句,返回结果。

二、Mybatis中的执行器

  • SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
  • ReuseExecutor:执行update或select以sql作为key查找statement对象,存在就使用,不存在就创建,用完后,不关闭statement对象,而是放置于Map<String,Statement>内,供下次使用,就是重复使用Statement对象。
  • BatchExecutor:执行update,将所有sql都添加到批处理中,等待统一执行,,它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executorBatch()批处理。

三、#{}和${}区别

#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?,调用PreparedStatement的set方法来赋值。
Mybatis在处理 ${}时,会把 ${}替换成变量的值。

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

四、为什么需要预编译

预编译可以优化SQL的执行。
防止sql注入。

五、为什么调用dao接口的方法就能调用sql查询数据,原理是什么

在第一步build的时候就会根据mapperXML里面的nameSpace拿到接口并且创建一个代理类工厂
newMapperProxy<>(type),存入knownMappers集合中,此时还没有创建代理类bindMapperForNamespace();同时会把sql语句放入mappedStatements的一个map中,再调用
session.getMapper(BlogMapper.class)方法时,会根据class创建一个代理类,并且返回代理类,执行方法时,执行的是我们代理类的方法MapperProxy,在代理类方法中,执行我们的逻辑,并且从MappedStatement拿到一开始就加载好的sql语句。

六、Mybatis的一级缓存和二级缓存

一级缓存:作用域为SqlSession,存在BaseExecutor下的PerpetualCache下的cache,默认开启,存在查询的方法里面。在同一个SqlSession中执行两次相同的SQL语句时,第一次执行完毕会将结果保存在缓存中,第二次查询直接从缓存中获取。
二级缓存:作用域为nameSpace
二级缓存开启需要2个条件
a.要有CachingExecutor,所以由cacheEnable配置决定,默认是true;
b.Mapper必须要有cache标签,也就是决定currentCache有没有
c.还要在sql上useCache标签为true,对于query语句默认为true,如果想关闭可以设置为false。
d.修改和删除都会清除缓存

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

<cache type="" size="" eviction = "LRU" flushInterval = "120000" 
readOnly="false" />

<select id="selectBlogById" resultMap="BaseResultMap" useCache="true" statementType="PREPARED" > select * from blog where bid = #{bid} </select>

<select id="save" parameterType="XX" flushCache="true" useCache="false"> 
</select>

七、Mybatis如何进行分页的

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内执行书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页,分页插件基本原理是使用M ybatis提供的插件口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql。

八、Mybatis延迟加载的原理

使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询管理B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。

九、Mybatis的xml映射文件和Mybatis内部数据结构之间的映射关系

Mybatis将所有xml配置信息都封装到All-In-One重量级对象Configuration内部,在Xml映射文件中,parameterMap标签会被解析为ParameterMap对象,其每个子元素会被解析为ParameterMapping对象,resultMap标签会被解析为ResultMap对象,其每个子元素会被解析为ResultMapping对象。每一个select、insert、update、delete标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象


总结

无论怎么样,每天都要进步一点点

Tags:

最近发表
标签列表