Mybatis源码学习-笔记

参考资料:https://www.open-open.com/ppt/e2d62f17112544eb93748c5dbe92d58c.html

疑问待解决:

spring-mybatis中SqlSessionTemplate

怎么执行sql的

 

一.Mybatis访问数据库步骤(非常重要  屡着源代码多看几遍)

1.读取配置文件(配置文件要包含数据库连接信息以及mapper文件地址)

2.创建SqlSessionFactoryBuild对象

3.通过SqlSessionFactoryBuild创建SqlSessionFactory工厂

4.通过SqlSessionFactory创建SqlSession对象

5.为DAO接口生成代理类

6.动态代理回调SqlSession某方法

7. SqlSession将要操作的方法转发给Executor(并组装好cacheKey)(paramHandle运用插件的原理)

11.把数据返回给调用者

8.去查询cacheKey是否命中,如果命中直接返回,如果没有命中

9.Executor交给StatementHandler去执行(里面有个statement.execute(sql)真正执行sql的操作-JDBC访问数据库操作数据)代理模式

10. Executor通过反射将数据封装POJO返回给sqlsession(resultParamHandle运用插件的原理)

11.把数据返回给调用者

写dao实现类怎么找到对应sql

sqlsession.selectlsit(namespace+sqlId);

不写dao实现类怎么找到对应的sql呢(怎么从dao-mapper)

class object = sqlseesion.getMapper(class);

object为mapper的代理对象

dafulatSqlSession->getMapper方法->mapperRegistry.getMapper->mapperProxyFactory.newInstance->Proxy.newProxyInstance(生成代理对象)

MapperProxy->都会去执行invoke方法->invoke里面都会执行mapperMethod.execute(this.sqlSession, args)

二.生命周期

SqlSessionFactoryBuilder 对象用于构建 SqlSessionFactory,只要构建好, SqlSessionFactoryBuilder 对象就可以丢弃了。SqlSessionFactory 是一个工厂类,一旦被创建 就应该在应用运行期间一直存在,不应该丢弃或重建。SqlSession 不是线程安全的,所以不 应被多线程共享。官方推荐的使用方式是有按需创建,用完即销毁。因此,以上步骤中,第 1、2 和第 3 步只需执行一次。第 4 和第 5 步需要进行多次创建

三.MyBatis VS Hibernate

Hibernate 可自动生成 SQL,降低使用成本。但同时也要意识到,这样做也是有代价的, 会损失灵活性。比如,如果当我们需要手动优化 SQL 时,会发现很难改变 Hibernate 自动生 成的 SQL。因此对于 Hibernate 来说,它适用于一些需求比较稳定,变化比较小的项目,譬 如 OA、CRM 等。(无法手动优化sql)

MyBatis 需要手动维护 SQL,这会增加使用成本。但同时,使用者可 灵活控制 SQL 的行为,这为改动和优化 SQL 提供了便利性。所以 MyBatis 适合应用在一些 需要快速迭代,需求变化大的项目中.

除此之外,MyBatis 还提供了插件机制,使用者可以按需定制插件。这也是 MyBatis 灵活性的一个体现。

四. Spring 中使用 MyBatis

数据源配置 Spring 配置文件中。配置完数据源,接下来配置 SqlSessionFactory。再接下来是配置 MapperScannerConfigurer,这个类用于 扫描某个包下的数据访问接口,并将这些接口注册到 Spring 容器中。这样,我们就可以在其 他的 bean 中注入 Dao 接口的实现类,无需再从 SqlSession 中获取接口实现类

延迟加载原理

使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

 

 五:插件原理

Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。

Mybatis分页插件安全性问题:

PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。

只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。

如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。

 

 

posted @ 2020-05-21 10:00  我是张某某  阅读(233)  评论(0)    收藏  举报