Java进阶笔记(二):Mybatis相关

​1.Mybatis动态sql作用

Mybatis动态sql可以灵活的根据某种条件拼接出需要的SQL语句,便于编写通用的SQL语句。

 

2.有哪些动态sql

<where>:可以代替SQL中的where,只会在子元素返回任何内容的情况下才插入 WHERE 子句。而且,若子句的开头为 AND 或 OR,where 元素也会将它们去除。

<if>:根据标签中的属性test指定的判断条件,满足条件则拼接其中的SQL语句,否则不拼接。

<foreach>:用来对集合进行遍历,一般与SQL语句where...in连用,查询符合条件的结果。

<choose><when><otherwise>:与Java中的switch类似,从多个条件中选一个执行拼接。

<set>:可以代替SQL中的set,可以动态配置set关键字,和剔除追加到条件末尾的任何不相关的逗号。

<sql><include>:使用sql标签抽出可以公用的SQL语句,使用include标签使用公用的SQL语句。

<trim>:可以完成set或者是where标签的功能。

<bind>:可以使用 OGNL 表达式创建一个变量并将其绑定到上下文中,可以避免因更换数据库而修改 SQL,也能预防 SQL 注入。

 

3.动态sql的执行原理

动态SQL的执行原理:动态SQL一般与普通SQL语句一起使用,位于xml文件中,或者使用注解的方式写在java文件中;当mybatis准备执行SQL时,会加载这些文件中对应的部分,获得普通SQL与动态SQL;如果发现动态SQL,则进行相应的特殊处理解析,最终生成可执行的SQL语句。

 

4.Mybatis是否支持延迟加载

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

 

5.Mybatis延迟加载的实现原理

使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,

将关联查询多张表的操作改为按顺序查询单张表的操作。

 

6.Mybatis的Executor执行器及区别

有3个执行器:

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch();完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

 

7.简述Mybatis的一级、二级缓存

一级缓存的存储结构是HashMap;

范围是SqlSession;

失效场景:只要SqlSession执行commit操作(不需要执行增删改查,已找到源码并测试),就会将这个SqlSession的一级缓存全部清空。

 

二级缓存的存储结构是HashMap;

范围是Mapper;

失效场景:开启二级缓存后,只有执行对应mapper的增删改操作并执行commit后,才会清空该mapper的整个二级缓存,只执行commit是不会清空的(已测试)

开启二级缓存后,执行select后,需要执行commit(或者close)方法,才会将查询结果提交给二级缓存,其它SqlSession查询时才能从二级缓存获取值;如果不执行commit(或close),则二级缓存没有数据。

 

8.Mybatis插件的运行原理

Mybatis支持给执行器Executor、SQL语法构建器StatementHandler、参数处理器ParameterHandler、结果集处理器ResultSetHandler这四大对象添加插件;当需要使用这些对象执行方法时,Mybatis会使用这些对象的代理对象,而代理对象已经在初始化时就添加了插件对象,因此具有插件的功能与原本的功能;代理对象执行方法时,就相当于执行了插件的方法与原对象本应该执行的方法。原理是AOP(面向切面)。

 

9.编写Mybatis插件的方法

(1) 新建一个自定义类作为插件类,实现Interceptor接口;

(2) 在这个类中使用@Signature注解指明要给哪个类的哪个方法加插件,也要写清楚那个方法的参数是什么;

(3) 在这个类中重写intercept方法做为插件方法;

(4) 在这个类中重写plugin方法,将这个插件(拦截器)添加到链中;

(5) 在这个类中重写setProperties方法,可以获取到一些配置参数;

(6) 在配置文件(例如sqlMapConfig.xml)中,添加<plugins>与<plugin>标签,注册插件;

(7) 编写测试类,查看插件是否生效。

 

posted @ 2020-10-14 08:43  codeToSuccess  阅读(97)  评论(0编辑  收藏  举报