mybatis原理

mybatis原理

mybatis原理

文章插图
1、API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵、数据库 。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理 。
2、数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等 。它主要的目的是根据调用的请求完成一次数据库操作 。
3、基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件 。为上层的数据处理层提供最基础的支撑 。
mybatis原理是什么MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架 。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索 。
MyBatis使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录 。
每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得 。用xml文件构建SqlSessionFactory实例是非常简单的事情 。
mybatis原理

文章插图
扩展资料:
mybatis的功能构架:
1、API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库 。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理 。
2、数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等 。它主要的目的是根据调用的请求完成一次数据库操作 。
mybatis如何进行分页,分页插件的原理【mybatis原理】在MyBatis内部定义了一个拦截器接口
所有的插件都要实现该接口,来,我们看看这个接口的定义
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
那么其中一个关键的方法就是intercept,从而实现拦截
分页插件的原理就是使用MyBatis提供的插件接口,实现自定义插件,在插件的拦截方法内,拦截待执行的SQL,然后根据设置的dialect(方言),和设置的分页参数,重写SQL,生成带有分页语句的SQL,执行重写后的SQL,从而实现分页
所以原理还是基于拦截器
Mybatis源码解析系列从命名上可以看出,这个是一个 Builder 模式的,用于创建 SqlSessionFactory 的类 。SqlSessionFactoryBuilder 根据配置来构造 SqlSessionFactory 。其中配置方式有两种:
mybatis-config.xml 就是我们的配置文件:
Java Config 相比较 XML 文件的方式而言,会有一些限制 。比如修改了配置文件需要重新编译,注解方式没有 XML 配置项多等 。所以,业界大多数情况下是选择 XML 文件的方式 。但到底选择哪种方式,这个要取决与自己团队的需要 。比如,项目的 SQL 语句不复杂,也不需要一些高级的 SQL 特性,那么 Java Config 则会更加简洁一点;反之,则可以选择 XML 文件的方式 。
创建配置文件解析器XMLConfigBuilder
解析mybatis-config.xml里的配置为Configuration对象,Mybatis的全局配置对象 。
XMLConfigBuilder#parseConfiguration解析mapper下的xml
XMLMapperBuilder#bindMapperForNamespace,根据xml里的 namespace 反射出 mapper接口 的 class,如果有mapper接口,则把该mapper接口的class添加到Configuration的mapperRegistry里 。
如果该接口已经注册,则抛出已经绑定的异常 。
为该接口注册MapperProxyFactory,但这里只是注册其创建MapperProxy的工厂,并不是创建MapperProxy 。
如果Mapper对应的xml资源未加载,触发xml的绑定操作,将xml中的sql语句与Mapper建立关系 。
addMapper方法,只是为**Mapper创建对应对应的MapperProxyFactory 。
根据Mapper接口与SqlSession创建MapperProxy对象 。
根据接口类获取MapperProxyFactory 。
调用MapperProxyFactory的newInstance创建MapperProxy对象 。
SqlSessionFactory 顾名思义,是用于生产 SqlSession 的工厂 。通过如下的方式来获取 SqlSession 实例:
SqlSession 包含了执行 SQL 的所有的方法 。以下是示例:
当然,下面的方式可以做到类型安全:
MapperProxy是MapperProxyFactory使用SqlSession创建出来的 。所以MapperProxy中包含SqlSession 。
可以看到MapperProxy调用invoke方法,进而调用MapperMethod的execute(),这些MapperMethod就是和你要执行的命令相关,比如执行select语句,则会通过SqlSession的select()方法,最终调用到Executor的query方法 。Executor会再协调另外三个核心组件 。
MapperProxy:
MapperMethod:
插件的构建:
谈原理首先要知道StatementHandler,ParameterHandler,Result Handler都是代理,他们是Configuration创建,在创建过程中会调用interceptorChain.pluginAll()方法,为四大组件组装插件(再底层是通过Plugin.wrap(target,XX, new Plugin( interceptor))来来创建的) 。
插件链是何时构建的:
在执行SqlSession的query或者update方法时,SqlSession会通过Configuration创建Executor代理,在创建过程中就调用interceptor的pluginAll方法组装插件 。然后executor在调用doQuery()方法的时候,也会调用Configuration的newStatementHandler方法创建StatemenHandler(和上面描述的一样,这个handler就是个代理,也是通过interceptorChain的pluginAll方法构建插件)
插件如何执行:
以statementhandler的prepare方法的插件为例,正如前面所说,statementhandler是一个proxy,执行他的prepare方法,将调用invokeHandler的invoke方法,而invokeHandler就是Plugin.wrap(target, xxx, new Plugin(interceptor))中的第三个参数,所以很自然invokeHanlder的invoke的方法最终就会调用interceptor对象的intercept方法 。
Mybatis的插件配置在configuration内部,初始化时,会读取这些插件,保存于Configuration对象的InterceptorChain中 。
org.apache.ibatis.plugin.InterceptorChain.java源码 。
上面的for循环代表了只要是插件,都会以责任链的方式逐一执行,所谓插件,其实就类似于拦截器 。
插件的编写
插件必须实现org.apache.ibatis.plugin.Interceptor接口 。
-intercept()方法:执行拦截内容的地方,拦截目标对象的目标方法的执行
-plugin()方法:决定是否触发intercept()方法 。作用:包装目标对象,包装就是为目标对象创建一个代理对象
-setProperties()方法:给自定义的拦截器传递xml配置的属性参数 。将插件注册时的property属性设置进来
下面自定义一个拦截器:
为什么要写Annotation注解?注解都是什么含义?
Mybatis规定插件必须编写Annotation注解,是必须,而不是可选 。@Intercepts注解:装载一个@Signature列表,一个@Signature其实就是一个需要拦截的方法封装 。那么,一个拦截器要拦截多个方法,自然就是一个@Signature列表 。
type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }
解释:要拦截Executor接口内的query()方法,参数类型为args列表 。
Plugin.wrap(target, this)是干什么的?
使用JDK的动态代理,给target对象创建一个delegate代理对象,以此来实现方法拦截和增强功能,它会回调intercept()方法 。
Mybatis可以拦截哪些接口对象?
Mybatis只能拦截ParameterHandler、ResultSetHandler、StatementHandler、Executor共4个接口对象内的方法 。
重新审视interceptorChain.pluginAll()方法:该方法在创建上述4个接口对象时调用,其含义为给这些接口对象注册拦截器功能,注意是注册,而不是执行拦截 。
拦截器执行时机:plugin()方法注册拦截器后,那么,在执行上述4个接口对象内的具体方法时,就会自动触发拦截器的执行,也就是插件的执行 。
Invocation
可以通过invocation来获取拦截的目标方法,以及执行目标方法 。
分页插件原理
由于Mybatis采用的是逻辑分页,而非物理分页,那么,市场上就出现了可以实现物理分页的Mybatis的分页插件 。要实现物理分页,就需要对String sql进行拦截并增强,Mybatis通过BoundSql对象存储String sql,而BoundSql则由StatementHandler对象获取 。
因此,就需要编写一个针对StatementHandler的query方法拦截器,然后获取到sql,对sql进行重写增强 。

    推荐阅读