首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mybatis全面总结

Mybatis全面总结

作者头像
小土豆Yuki
发布2021-06-15 15:14:00
3240
发布2021-06-15 15:14:00
举报

Mybatis缓存机制

Mybatis定义了两级缓存,一级缓存和二级缓存,

  • 默认情况下只有一级缓存
  • 二级缓存需要手动开启,且他是namespace级别的
  • 定义了缓存接口cache,可以实现cache接口自定义二级缓存

一级缓存,即本地缓存,作用域默认为sqlSession,本地缓存不能关闭,但是可以清空,同一次会话期间只要查询过的数据都会保存在当前sqlsession的一个map中,

一级缓存失效的情况如下

  1. 不同的sqlsession对应不同的一级缓存
  2. 同一个sqlsesion,但是查询条件不同
  3. 同一sqlsession两次查询期间进行了增删改操作
  4. 同一个sqlsession两次查询手动清空了缓存

二级缓存,全局作用域的缓存,默认是不开启的,Mybatis提供二级缓存的接口以及实现,缓存实现要求POJO实现Serializable接口,二级缓存sqlSession关闭或提交之后才会生效

//全局配置文件开启二级缓存
<setting name="cacheEnabled" value="true"/>
//对应的映射文件使用caceh配置,且对应的对象要实现Serializable
<cache />

cache标签重要属性的含义

evication

缓存回收策略

LRU,对近最少FIFO,先进先出,按照进入缓存的顺序删除SORT,软引用,移除垃圾回收器和软引用规则的对象WEAK(移除基于垃圾收集器装器和弱引用规则的对象)

flushInterval

刷新间隔单位毫秒

默认不设置,没有刷新间隔,缓存仅仅调用语句时候刷新

size

缓存的对象多少

readOnlya

只读

true:会给所有调用者返回缓存对象的相同实例,因为这些对象不能被修改false.会返回缓存对象的拷贝,

缓存的有关配置

  • 全局setting的cacheEnable,配置二级缓存的开关
  • select的useCache属性,是否使用二级缓存
  • sql标签,flushCache,ture:同时清空一级二级缓存,
  • sqlsession.cleatcache,只清除一级缓存
  • 当一个作用域进行了增删改,默认该作用域下的缓存被clear

可以使用第三方缓存框架如EhCache

<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

当一条sql执行的时候,先从二级缓存中查询,再到一级缓存查询,最后走到数据库查询.

Mybatis工作原理

  1. 根据配置文件初始化configuration对象,创建sqlsessionFactory
  2. 在sqlSessionFactory创建一个DefaultSqlSession对象,里面包含了Exectuor和Configuration
  3. DefaultSqlSession.getMapper,拿到Mapper接口对应的MapperProxy
  4. MapperProxy里面有DefaultSqlSession
  5. 执行增删改查,
    1. 调用DefaultsqlSession的增删改查,
    2. 创建一个StatementHandler对象,同时也创建Paremeterhander和ResultSetHandler
    3. 调用Statementhandler预编译参数以及设置参数,使用parameterhandler给sql设置参数值
    4. 调用statementhandler的增删改查方法
    5. 使用ResultSetHandler封装结果

Mybatis插件开发

在Mybatis四大对象创建的时候,都会有插件的进行介入,插件可以利用动态代理机制一层层的包装目标对象,而实现在目标对象方法之前进行拦截的效果

开发步骤如下

  1. 编写插件实现Interceptor接口,并使用Intercepts注解完成插件签名
  1. 全局配置文件中注册插件

插件原理

  • 按照插件注解声明,按照插件配置顺序调用插件plugin方法,生成拦截对象的动态代理
  • 多个插件依次生成目标对象的代理对象,层层包裹,先声明的先包裹没形成代理链
  • 目标依次从内到外执行
  • 多个插件情况下,我们往往需要分离出目标对象,可以借助mybatis提供的SystemMetaObject类进行获取最后一层的h以及target属性的值

#{}和${}区别

  1. #{}是预编译处理,${}是字符串替换
  2. #{}会替换成?,在PrepatedStatement的set方法赋值
  3. ${}是直接替换成值
  4. #{}可以预防sql注入,提高系统安全性

Mybatis映射文件中,如果标签A通过引用B标签的内容,请问,B标签能否在A标签后面,还是说必须定义在标签A的前面

虽然Mybatis解析XML映射文件是按照顺序解析的,但是被引用的标签B依然可以定义在任何地方,因为当解析到标签A的时候,发现标签B尚未解析到,可以标记标签A为未解析,然后继续解析其他标签,当所有标签解析完毕之后,Mybatis会重新解析那些标签未解析的标签,此时在解析A标签时候,标签已经存在,A标签也就可以正常解析了

Mybatis有哪些Executor执行器,他们之间的区别是什么

Mybatis有三种基本的Executor执行器

  1. SimpleExecutor,每次执行一次update或select,就开启一个Statement对象,用完立刻关闭statement对象
  2. ReuseExecctor,执行update或select,以sql作为key查找statement对象,如果存在就使用,如果不存在就创建用完后,不关闭statement对象,放在与map
  3. BatchExecutor,完成批处理

Mybatis是否支持延迟加载,如果支持,他的实现原理是什么

Mybaits仅支持association关联对象和Collection关联集合对象的延迟加载,association指的是一对一,collection指的是一对多查询,Mybatis配置文件中,可以配置是否开启延迟加载,lazyLoadingEnabled=true|false

他的原理是,使用CGLIB创建目标对象的代理,当调用目标对象的时候,进入拦截方法,比如调用a.getB().getName().当拦截器发现a.gerB对象时null的时候,就会单独发送事先保存好的查询B对象的sql,把对象B查询上来之后,然后调用a.setB(b),于是a就可以获取B对象,接着完成getName()调用,值就是延迟加载

持续关注,下一篇分布式全面总结,如果对您有一丝丝帮助,麻烦点个关注,也欢迎转发,谢谢

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 洁癖是一只狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档