作为常用的orm框架,mybatis承接了SQL的预编译,执行,响应结果映射等SQL处理的各个环节。在这里整理下这个框架的一些知识点,方便后续复习。
原生的mybatis初始化流程如下图所示:
在XMLConfigBuilder中针对xxxMapper.xml文件进行了初始化,转换成了MapperStatement对象缓存到了Configuration中。后续SQLSession使用时基于statementId定位到MapperStatement发起具体的执行。
在spring环境中,会基于mybatis-spring将mapper注册为一个spring的bean,然后基于IOC框架注入到各个依赖点。
springboot中,mybatis的初始化流程如下:
这个流程比较有意思的是在SqlSessionTemplate,其中内置了一个sqlsessionProxy,其代理了所有的SQL请求,在具体执行时,会在事务开始时动态生成一个sqlsession,后续一个事务内的都会共享一个sqlsession。而在MapperProxy中的sqlsession是sqlsessionTemplate自己,相当于2层代理。第一层是MapperProxy,其将Mapper对外动态创建了一个Spring的Bean,然后业务调用mapper的method时,是请求到了sqlSessionTemplate的实例,然后内部又是通过sqlsessionProxy发起真实的请求。
sqlSession发起执行后,会筛选出具体的MapperStatement,然后委托给executor具体执行,一般都是使用的SimpleExecutor,然后看是否开启二级缓存进而在其上包装一个CacheExecutor。
sqlsession的一级缓存是默认开启的,也可以通过一定的方式进行缓存的强制刷新,一级缓存的生命周期是sqlsession级别的,事务或者会话结束,则缓存无效。二级缓存需要在Mapper.xml中主动声明才能开启,因为其生命周期是namespace的,会跟随应用的整个生命周期,启用与使用都要慎重一些。二级缓存不会因为事务失败污染缓存数据,其在事务内会分离出一个事务缓存,事务成功才提交数据到真实缓存,事务失败则移除缓存数据。
mybatis的插件机制是每次申请相关组件都会进行动态代理包装,这个如果不是一个事务内,查询很频繁的话,这种层层包装的插件机制,也会带来性能损耗,如无必要,不要配置太多插件。
参考资料:
https://juejin.im/post/5db92c41f265da4d0a68d161