关于Mybatis的一些问题讨论

Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理

动态sql的用途

Mybatis动态sql的主要是为使用者提供了可以动态变更sql的能力.也就是可以根据使用者传入的参数来动态拼接sql,以便让sql可以复用.

动态sql的类型

if标签


主要用于添加判断,如果test中的内容为true,则if中的text会添加到sql中

where标签


where标签一般不会单独使用,它的主要作用是为了配合其他的标签来判断是否需要加入where语句,以避免sql语句报错

choose,when,otherwise


    
                
    
    
                
    

这三个标签需要连用,首先由choose标签开启判断,类似于if else的结构

set


类似where标签,是为了在update时动态判断是否需要添加set时的标签

trim



trim是一个比较强大的标签,可以通过前缀,后缀,前缀重写和后缀重写来实现各种语句的拼接,比如上面的set,where标签

foreach



遍历标签,可以遍历传入的参数,配合前缀,后缀以及中间的间隔符,可以实现批量操作.

动态sql的执行原理

  1. 加载sqlMapConfig.xml文件以获取mapper.xml文件的位置
  2. 加载mapper.xml文件
  3. 扫描出各种节点
  4. 将扫描后的节点在加载过程中调用XMLStatementBuilder的方法来返回SlqSource对象
image.png
  1. 接着在XMLScriptBuilder中调用如下方法来解析动态标签
image.png
  1. 并在这个方法中选择对应的动态标签handler来处理
image.png
  1. 最终返回了一个sqlSource对象.这个对象唯一的方法就是返回boundSql
image.png
  1. 此时使用还是原来的流程来操作boundSql即可.

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

Mybatis主要有以下几个Executor执行器

image.png

区别

其实可以见名知意.

  • CachingExecutor是BaseExecutor的一个包装.添加了关于二级缓存的相关内容
image.png

图中标红的位置就是BaseExecutor的一个实现.

  • BaseExecutor是一个基于一级缓存的默认实现父类,对一级缓存机型管理.对于后续调用handler的处理会交给子类来完成
image.png

图中标红的位置是一个抽象方法,所以会调用子类的实现

  • SimpleExecutor是基本的Executor实现类,默认会使用它.它和ReuseExecutor的最大区别在于Statement是否会重用.
image.png

可以看到没有关于Statement的信息

  • ReuseExecutor内部缓存了statement,会重用Statement.
image.png

可以看到有一个statement的缓存,同时名字也有提到,是一个reuse的作用,所以区别主要在用是否重用Statement.

  • BatchExecutor是基于批处理提供的Executor,主要用于批处理的更新和查询
image.png

批处理的则和其他的处理器的逻辑完全不一样.

简述一下Mybatis的一级,二级缓存(分别从存储结构,范围,失效条件.三个方面来作答)?

一级缓存

存储结构

image.png
image.png

如图所示,是使用hashmap的结构来存储缓存的.

范围

一级缓存的范围仅限于SqlSession层级.如下图逻辑所示

  1. 创建sqlSession
image.png
  1. 创建Executor
image.png

3.创建我们的缓存类.并在缓存类初始化时创建hashmap

image.png

失效条件

当执行update操作时,会对应的清除一级缓存.

image.png

二级缓存

存储结构

image.png

可以看到这里默认的二级缓存和一级缓存的结构是一样的,也是hashmap

范围

二级缓存的范围是整个mapper.对于所有的sqlSession是公用的.

image.png

如果二级缓存开启会使用CachingExecutor,会取上面创建mapper时创建的缓存使用

失效条件

image.png
image.png

更新时会判断是否需要清空缓存.如果此时判断需要,则缓存会被清空.

简述Mybatis的插件运行原理,以及如何编写一个插件.

Mybatis有四大对象被允许拦截并创建出代理对象,分别是

  • Executor
  • StatementHandler
  • ParameterHandler
  • ResultSetHandler
  1. Mybatis会获取所有的interceptor,并使用责任链模式来依次调用interceptor的plugin方法.
  2. 插件实现interceptor并加入责任链中,并在intercept方法中实现自己的invcation.
  3. 当责任链调用到插件时,需要判断对象是否是我们需要拦截的对象.如果是,则调用plugin的wrap方法,此时会根据你的invocation来动态生成一个代理对象并返回.
  4. 最终责任链执行完毕后会返回最后的一个代理对象.

如何编写一个插件

  1. 实现mybatis提供的interceptor接口,并实现对应的方法.
  2. 在实现类添加类注解,并在代码中判断是否需要生成代理类.
image.png
  1. 将接口全路径配置在sqlMapConfig中,以便获取自定义的插件

你可能感兴趣的:(关于Mybatis的一些问题讨论)