From 8516c31fccfdcac5683486a014ed76edac4a451a Mon Sep 17 00:00:00 2001 From: Rikako Wu <496063163@qq.com> Date: Thu, 1 Sep 2022 01:18:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=B8=B8=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mybatis/mybatis.md | 333 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) diff --git a/mybatis/mybatis.md b/mybatis/mybatis.md index acb9c2a..1144d5f 100644 --- a/mybatis/mybatis.md +++ b/mybatis/mybatis.md @@ -496,3 +496,336 @@ public class User { - typeHandler - resultMap - select +### association元素 +association元素通常用来标识“has-a”的关系,通过关联,有两种方式将数据加载到关联中去 +- 嵌套select:执行另一个sql statement并且返回预期的复杂对象 +- 嵌套result:通过嵌套的result mapping来处理连接结果的重复子集 +#### 嵌套select +嵌套select,其会先返回查询的主表数据,对关联的子表数据会通过association标签指定的select属性值来再次执行sql查找预期数据并组装城复杂对象 +当使用嵌套select来处理association时,association标签具有如下属性: +- column:数组库表的列名,该列保存的值将会被传递给嵌套的statement作为输入参数。 +> 当想要传递复合key作为输入参数时,可以通过column="{prop1=col1,prop2=col2}"的形式来传递参数,这会导致传递给嵌套statement的参数对象的prop1和prop2属性被设置 +- select:会返回预期复杂类型的其他select statement标签的id +- fetchType:可选参数,可以为“lazy”或者“eager”,会覆盖全局配置中的lazyLoadingEnable +```xml + + + + + + + + +``` +> 对于嵌套select方法来加载association,其会导致***N+1***的问题 +> 例如,当一条select语句返回一个数据集时,通过嵌套select语句来加载association,其会: +> #### 对数据集中的每一条数据,都会再次执行一个select语句来为该条数据加载association信息,当数据集中数据条数很多时,如果未设置延迟加载,那么成百上千的sql语句被执行,会严重影响性能 + +#### 嵌套result +不同于嵌套select先查主表信息后再次执行sql语句查询关联子表数据,嵌套result会通过A JOIN B关联来通过查询需要的主表信息和子表信息 +嵌套result不需要像嵌套select一样分次执行sql语句 +> #### 使用嵌套result时association可以使用的属性 +> - resultMap:指定用于将results加载到association的resultMap id +> - columnPrefix:可以将具有某一个前缀的列映射到外部的resultMap中,从而即使在select语句中重新为列名定义了alias(添加了前缀,如"co_"等),还是能复用外部的同一个resultMap +> - notNullColumn:该属性可以指定多个列,只有当指定的多个列中任何一个不为空时,mybatis +> 才会创建该子对象 +> - autoMapping:开启或关闭自动映射,该属性对外部映射无效,故而不能搭配select或者resultMap使用 +```xml + + + + + + + + + + + + + + + + + +``` +> 在嵌套result中,id元素(被标识为id的result)非常重要,应该指定一个或多个属性标识为id来唯一标识该对象. +> 当没有指定id result时,mybatis也会正常运行,但是会产生严重的性能问题 +> 应尽可能的将能唯一标识该结果的最小字段集标识为id(可以选择主键或符合主键) + +对于嵌套result,除了上述的办法,还可以将association对应的resultMap直接嵌套写入association的子标签中,样例如下: +```xml + + + + + + + + + + + +``` +共同作者:通过columnPrefix属性复用外部resultMap的情况 +```xml + + + + + + + + + + + + + + + + + + +``` +### collection元素 +collection元素用来处理A类中含有List<B>属性的情况,其用法基本和association元素相同 +```xml + + + + + +``` +和association元素相同,coolection元素也可以通过嵌套select或者嵌套result来映射复杂类型 +#### collection元素的嵌套select +```xml + + + + + + + +``` +#### collection元素的嵌套result +```xml + + + + + + + + + + + + + + + + + + + + + + + + +``` +## discriminator +某些情况下,单条sql查询语句会返回具有不同类型的结果集(如不同的Car数据,但是有卡车和轿车的区别). +discriminator可以通过某些字段的值来选择性采用某些resultMap,并且支持继承层次. +```xml + + + + + + + + + + + + + + + + + + + +``` +如果想要在使用carResult时也执行vehicleResult中的映射,可以在carResult中指定extends属性 +```xml + + + +``` +## automapping +对于automapping,其会获取resultset中的字段名并且在java对象中查找同名的property(忽略大小写,如果想将数据表字段名的underscore形式映射到java类的camelCase属性,可以在mybatis config文件中添加mapUnderscoreToCamelCase配置). +即使手动指定了resultMap,automapping一样会发挥作用.对于每个指定的resultMap,所有在resultSet中出现过的字段如果没有在resultMap中手动为其配置一个映射,那么会对该字段执行automapping. +```xml + + + + + + +``` +> 自动映射有三种等级,可以在mybatis config文件中进行配置 +> - NONE:禁用自动配置 +> - PARTIAL:会对除嵌套result映射以外的属性进行自动行摄 +> - FULL:会对所有属性执行自动映射 +```xml + + + + + + + + + + +``` +默认情况下,automapping级别为partial,并且可以为resultMap元素指定autoMapping属性为false来为该resultMap关闭autoMapping +```xml + + + +``` +## mybatis缓存 +默认情况下,mybatis只启用了会话级别的缓存,其缓存数据只在sqlsession期间有效. +如果想要开启二级缓存,只需要在接口对应的mapper文件中添加一行 +```xml + +``` +该行语句的效果如下: +- 所有select语句的执行结果都会被缓存 +- 所有insert/update/delete语句都会清除缓存 +- 缓存会通过LRU算法来作为淘汰策略 +- 缓存不定期的刷新 +- 缓存会存储1024个引用指向列表或者对象(不管查询方法会返回哪种类型) +- 缓存被设计为可读写缓存,通过缓存获取到的对象并不会和其他线程共享,故而可以安全的对获取到的对象进行共享 +> 缓存只会作用于位于mapper文件中的语句,如果使用java api和xml混合的方式,那么在共用接口声明的sql语句并不会被缓存. + +可以自定义二级缓存 +```xml + + +``` +对于二级缓存,可以使用的淘汰策略有: +- LRU:默认策略 +- FIFO +- SOFT:基于垃圾回收器状态和软引用规则移除对象 +- WEAK:弱引用,基于垃圾回收器状态和弱引用规则移出对象 + +flushInterval: +- 定义cache的刷新间隔,单位为ms,默认没有刷新间隔 + +size: +- 定义缓存大小,为引用数目,默认为1024 + +readOnly: +- true:只读,会给所有调用者返回相同的缓存对象实例,调用者如果进行修改可能会产生线程安全问题 +- false:可读写,会给所有调用者返回缓存对象的拷贝,调用者可以安全的对返回对象进行修改,默认情况下缓存类型是可读写的 + +> ### 二级缓存的事务性 +> 当sqlsession完成并且提交,或完成并回滚时,即使没有执行flushCache=true的insert/delete/update,缓存也会进行刷新 + +> select/update/insert/delete +> sql语句都会有flushCache属性,指定是否在执行完成后刷新cache,默认情况下,select标签的flushCache属性为false,insert/update/delete语句的flushCache属性为true + +### cache-ref +默认情况下,某一命名空间中的语句只会对当前命名空间中的cache进行刷新.但是,如果想在多个命名空间(Mapper)之间共享缓存,可以通过cache-ref来引用其他命名空间中的缓存. +```xml + +``` \ No newline at end of file