咕泡-MyBatis 实用篇作业

1. Mapper在spring管理下其实是单例,为什么可以是一个单例?

  • 首先,mapper 内部不包含 成员字段,无状态单例是安全的
  • 另外,一直存在不用每次调用都new 一个新实例

2. MyBatis在Spring集成下没有mapper的xml文件会不会报错,为什么?

  • 不会报错,因为支持 xml 和 annotation 两种

3. TypeHandler手写

  • 继承自 BaseTypeHandler
  • public class ExampleTypeHandler extends BaseTypeHandler<Date>
  • 配置到configuration 里面

d8d7265116e3e4a88d0e63bf081141c919d.jpg

  • 具体使用

62ee414665b7ef1e62a3177c0fb8cd2abd7.jpg

  • 比如 String 和Date 之间的互转

00b165d7321aeac87f27b7545b454486bff.jpg

4. 手写Plugin,多个interceptor到底谁先执行?顺序由谁决定的?

  • 允许使用插件拦截的接口

ee70f77cff52ba8f2825cfb8d48acd88d8a.jpg

  • 根据签名判断其拦截点,根据jdbc 执行顺序,执行到相应的点,进行执行

570071af2387493ed6985e3a6cf3893e7b8.jpg

  • 配置到 configuration 里面

0c44e9ad999fbfbd5459a3138d2f30ff23d.jpg

1.怎么验证一级缓存的存在?

  • 相同的查询,连续查询两遍,记录查询用时,会发现第二次快得多
  • update、 insert、delete 等语句会触发清除缓存
  • 一级缓存默认开启,SqlSession 级别的
  • 二级缓存默认关闭,SqlSessionFactory 级别的 

二级缓存是需要配置来开启的:

801e13c5489bb01ca9ad706038d846acd39.jpg

  • 所以,一级缓存,在存在俩sqlsession 时,可能存在脏数据的情况
    •  比如,sqlsessionA 两次相同查询t 表中间,sqlsessionB 更新了t表数据,第二次查询的数据就是可能已被修改的脏数据

2.验证N+1问题

  • 所谓级联查询(嵌套查询)

9677ff0739a830506a3f441fb410ee55d5e.jpg

  • 外层查询的一条结果数据,由内层查询获得
  • 外层查询一次,获得结果数N ,就要进行N 次内层查询(官方不鼓励使用,这样产生大量1+N次查询)

由于1+N 问题的性能损耗,可以考虑配合使用 延时加载

9d09a96b96aec622d7bbb3b9c00d7e1e234.jpg

  • 配置到 configuration 里面

0a870bbac0473b59e6a71f0ccaa261a8fae.jpg

1、TestMapper 作者为什么要设计这样的形式来做?为什么不是一个class而是一个interface?

  • 首先使用 interface 接口已经可以满足,根据全限定名+方法名找到对应的SQL语句,然后MapperProxy代理实现具体的执行
  • 所有的执行套路都是一样的,xml文件里面配置也很清楚了,不需要class
  • 保留interface 的原因是用户使用方便

2.org.apache.ibatis.executor.BaseExecutor#queryFromDatabase 322行这行代码的意义

  • 322行这行代码的意义是声明一个占位符,当发送一次查询数据的请求时,设置该占位符 告诉其他请求 正在查询数据库,请其他请求先阻塞或休眠。
  • 当这次请求查询到数据之后,将真正的数据放到占位符的位置,缓存数据。如果其他请求与该次请求查询的数据时一样的,直接从缓存中拿数据减少了查询请求对数据库的压力

df866be1fa5ec0a2ff1933996b97daeb3f6.jpg

3.MyBatis的plugin实现机制

  • interceptorChain.pluginAll(executor) 在configuration 内部注册所有的 plugin

0c4fb863d99a0eca374000f5d791d4a1818.jpg

  • 本质就是getSignatureMap 方法,扫描所有注解,对配置的Signature 方法进行 动态代理
     

ff4b8d7f99c2c3986b2f5396761aa51dc22.jpg

  • 代理类就是public class Plugin implements InvocationHandler
  • 执行Plugin 的invoke 会判断该方法是否被代理(signatureMap 里面有没有)

95bba58a50601c5201ff383d99794e4d804.jpg

  • 如果有执行 intercept 方法

8b951a7eec24e59e18bde8ed441b3a2c7ed.jpg

  • 该方法最后一行执行的proceed 方法,其实就是该方法的invoke 执行

6a8a2fa73c784edc2aa33b7de565f73b1b0.jpg

4.lazy loading 是怎么做到的?

  • 懒加载在级联查询时用到了,SimpleStatementHandler 里面query结果

e4875266370ee2a6a6afcb92c611099c119.jpg

  • DefaultResultSetHandler 处理结果
  • handleResultSets -->handleResultSets -->...getRowValue-->createResultObject 

dccef0be0f548d0baa16d07fbb9297eb8ba.jpg

  • 如果有嵌套查询且开启了懒加载 那么会使用代理工厂来处理(代理工厂类型cglib或javasissit类型(默认))
  • 针对某一个属性,当执行

480969f61caf1970cfa5e12142134a95efd.jpg

  • protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));
  • 在嵌套查询的时候 get/set 方法会触发 ResultLoaderMap LoadPair load() 方法去查询(我看源代码的理解),我找到了触发函数lazyLoadTriggerMethods 里面没有get/is  依赖的是PropertyNamer.isGetter(methodName)

转载于:https://my.oschina.net/u/3847203/blog/2088288

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值