了解SqlSession的运作原理是学习Mybatis插件的必经之路,因为Mybatis的插件会在SqlSession运行过程中“插入”运行,如果没有很好理解的话,Mybatis插件可能会覆盖相应的源码造成严重的问题。鉴于此,本篇博文尽量详细介绍SqlSession运作原理!
建议:在我之前的博文《Mybatis缓存(1)——–系统缓存及简单配置介绍》中介绍到SqlSession的产生过程,可以先理解后再读此博文可能会更加好理解!
注:本篇博文也是我最近真正理解Mybatis才开始编写的,可能有些地方不太准确,如果有错误之处敬请指出,另外创作不易,望转载告之,谢谢!
参数资料:《深入浅出Mybatis基础原理与实践》(我这里只有电子版PDF,需要的朋友可以联系我)
SqlSession提供select/insert/update/delete方法,在旧版本中使用使用SqlSession接口的这些方法,但是新版的Mybatis中就会建议使用Mapper接口的方法。
映射器其实就是一个动态代理对象,进入到MapperMethod的execute方法就能简单找到SqlSession的删除、更新、查询、选择方法,从底层实现来说:通过动态代理技术,让接口跑起来,之后采用命令模式,最后还是采用了SqlSession的接口方法(getMapper()方法等到Mapper)执行SQL查询(也就是说Mapper接口方法的实现底层还是采用SqlSession接口方法实现的)。
注:以上虽然只是简单的描述,但实际上源码相对复杂,下面将结合源码进行简单的介绍!
(2)SqlSession重要的四个对象
1)Execute:调度执行StatementHandler、ParmmeterHandler、ResultHandler执行相应的SQL语句;
2)StatementHandler:使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement;
3)ParammeterHandler:处理SQL参数;
4)ResultHandler:结果集ResultSet封装处理返回。
执行器起到至关重要的作用,它是真正执行Java与数据库交互的东西,参与了整个SQL查询执行过程中。
1)主要有三种执行器:简易执行器SIMPLE(不配置就是默认执行器)、REUSE是一种重用预处理语句、BATCH批量更新、批量专用处理器
/
- @author Clinton Begin
*/
public enum ExecutorType {
SIMPLE, REUSE, BATCH
}
复制代码
2)执行器作用:Executor会先调用StatementHandler的prepare()方法预编译SQL语句,同时设置一些基本的运行参数,然后调用StatementHandler的parameterize()方法(实际上是启用了ParameterHandler设置参数)设置参数,resultHandler再组装查询结果返回调用者完成一次查询完成预编译,简单总结起来就是即先预编译SQL语句,之后设置参数(跟JDBC的prepareStatement过程类似)最后如果有查询结果就会组装返回。
首先,以SimpleExecutor为例,查看源码我们得到如下几点重要知识点:
第一:Executor通过Configuration对象中newExecutor()方法中选择相应的执行器生成
第二:在执行器中StatementHandler是根据Configuration构建的
(2)StatementHanlder数据库会话器
1)作用:简单来说就是专门处理数据库会话。详细来说就是进行预编译并且调用ParameterHandler的setParameters()方法设置参数。
2)数据库会话器主要有三种:SimpleStatementHandler、PrepareStatementHandler、CallableStatementHandler,分别对应Executor的三种执行器(SIMPLE、REUSE、BATCH)
我们从上述Executor的prepareStatement()方法中调用了StatementHandler的parameterize()开始一步步地查看源码,如下得到几点重要的知识点:
第一:StatementHandler的生成是由Configuration方法中newStatementHandler()方法生成的,但是正在创建的是实现了StatementHandler接口的RoutingStatementHandler对象
switch (ms.getStatementType()) { case STATEMENT: delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case PREPARED: delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case CALLABLE: delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; default: throw new ExecutorException("Unknown statement type: " + ms.getStatementType()); }
第三:在BaseStatementHandler中重写prepare()方法,instantiateStatement()方法完成预编译,之后设置一些基础配置(获取最大行数,超时)
作用:对预编译中参数进行设置,如果有配置typeHandler,自然会对注册的typeHandler对参数进行处理
查看并学习源码,得到以下几点重要知识点:
第一:Mybatis提供了ParamterHandler的默认实现类DefalutParameterHandler
Object getParameterObject();
第二:从parameterObject中取到参数,然后使用typeHandler(注册在Configuration中)进行参数处理:
作用:很简单,就是组装结果返回结果集
第一:ResultSetHandler接口,handlerResultSets()是包装并返回结果集的,handleOutputParameters()是处理存储过程输出参数的
List handleResultSets(Statement stmt) throws SQLException;
Cursor handleCursorResultSets(Statement stmt) throws SQLException;
第三:在Executor中doQuery()方法返回了封装的结果集
SqlSession的运行主要是依靠Executor执行器调用(调度)StatementHandler、parameterHanlder、ResultSetHandler,Executor首先通过创建StamentHandler执行预编译并设置参数运行,而整个过程需要如下几步才能完成:
由适配模式生成的RoutingStatementHandler根据上下文选择生成三种相应的XXXStatementHandler;
在生成的XXXStatementHandler内部instantiateStatement()方法执行底层JDBC的prepareStatement()方法完成预编译
2)parameterize设置参数
默认是DefaultParameterHandler(实现了parameterHandler接口)中setParameter()方法完成参数配置,其中参数从ParameterObject中取出,交给typeHandler处理
3)doUpdate/doQuery执行SQL
返回的结果通过默认的DefaultResultSetHandler(实现了ResultSetHandler接口)封装
(2)运行图总结
1)SqlSession内部总运行图
2)prepare()方法运行图: 3)parameterize()方法运行图
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224155.html原文链接:https://javaforall.net
