当前位置: 移动技术网 > IT编程>开发语言>Java > MyBatis 源码分析 之SqlSession接口和Executor类

MyBatis 源码分析 之SqlSession接口和Executor类

2019年07月22日  | 移动技术网IT编程  | 我要评论

挡不住的风情 qvod,我和老婆的遭遇,等离子电视尺寸

mybatis框架在操作数据的时候,离不开sqlsession接口实例类的作用。可以说sqlsession接口实例是开发过程中打交道最多的一个类。即是defaultsqlsession类。如果笔者记得没有错的话,早期是没有什么getmapper方法的。增删改查各志有对应的方法进行操作。虽然现在改进了很多,但是也保留了很多。我们依旧可以看到类似于selectlist这样子的方法。源码的例子里面就可以找到。如下

sqlsession session = sqlmapper.opensession(transactionisolationlevel.serializable);
  try {
   list<author> authors = session.selectlist("org.apache.ibatis.domain.blog.mappers.authormapper.selectallauthors");
   assertequals(2, authors.size());
  } finally {
   session.close();

当然从某种意义上来讲,写起有一点烦。但是不可否认他的功能的确存在。这也是笔者为什么比较喜欢用动态代理来进行数据上的操作。至少可观性上笔者认为比较好吧。

不管是哪一种数据上的操作都离不开sqlsession接口实例。所以深入查看qlsession接口实例就显得相当的重要。笔者选择了defaultsqlsession类的selectlist方法作为入口点进行切入。代码如下。

public <e> list<e> selectlist(string statement, object parameter, rowbounds rowbounds) {
  try {
   mappedstatement ms = configuration.getmappedstatement(statement);
   return executor.query(ms, wrapcollection(parameter), rowbounds, executor.no_result_handler);
  } catch (exception e) {
   throw exceptionfactory.wrapexception("error querying database. cause: " + e, e);
  } finally {
   errorcontext.instance().reset();
  }
 }

源码的意思是从configuration变理里面获得,在通过executor类的query方法获得相应的结果。让我们想想上一章中讲过mappedstatement类是用于存放select节点或是update节点的信息。也就是说这里传入statement参数表示将要去执行哪一个select节点。传入的参数自然就是select节点id对应的值。那么executor类又是什么。如果比较认真的人来查看源码的话,你会发现基本上都会用到executor类实例。在一次叹气——架构之美。

defaultsqlsession类的成员executor是在构造函数里面给他赋值的。所以我们又要回头去查看一下是在什么时候实例化了defaultsqlsession类。笔者在第一章结尾的时候也讲到过关于executor类。从源码中我们可以看到他是通过configuration类的newexecutor方法来得到的。代码如下

public executor newexecutor(transaction transaction, executortype executortype) {
  executortype = executortype == null ? defaultexecutortype : executortype;
  executortype = executortype == null ? executortype.simple : executortype;
  executor executor;
  if (executortype.batch == executortype) {
   executor = new batchexecutor(this, transaction);
  } else if (executortype.reuse == executortype) {
   executor = new reuseexecutor(this, transaction);
  } else {
   executor = new simpleexecutor(this, transaction);
  }
  if (cacheenabled) {
   executor = new cachingexecutor(executor);
  }
  executor = (executor) interceptorchain.pluginall(executor);
  return executor;
 }

 完了。没有想到executor类还有分种类的。说实话笔者若是没有去查看源码真不会知道原来executor类还有分种类的。看上面的源码笔者刚开始认为有四种。但是发现最后一个跟上面的三个实例上有一点不同。为了更进一步确认笔者不得不去查看一下官网上面的api。笔者把内容复制过来。如下。

executortype.simple: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。

executortype.reuse: 这个执行器类型会复用预处理语句。

executortype.batch: 这个执行器会批量执行所有更新语句,如果 select 在它们中间执行还会标定它们是 必须的,来保证一个简单并易于理解的行为。

看样子官网解释的很清楚了。笔者就不在这里多言了。那么默认情况下mybatis框架又是调用哪一个executor子类呢?其实这一点是可以在源码上找到的。如下

configuration类:

protected executortype defaultexecutortype = executortype.simple;

相信大家都明白了如果都没有指定相应的executor类的类型的话,mybatis框架会去调用simpleexecutor类。

对于executor类我先了解到这里。因为后面大量要用到他,同时也只有结合后面的功能才明白executor类的作用。从上面defaultsqlsession类的selectlist方法中我们可以发现最后会去调用executor类的query方法。

return executor.query(ms, wrapcollection(parameter), rowbounds, executor.no_result_handler);

对于变量ms笔者就不多说了。wrapcollection方法却是值得注意的。他意思是先判断变理parameter是否是collection类型,如果是,就是新建一个strictmap类型并以“collection”为key进行存放。又查一下是不是list类型。如果是,就以“list”为key进行存放。接下就是判断是不是数组类型,如果是,就是新建一个strictmap类型并以“array”为key进行存放。最后返回回strictmap类实例。当然如果上面都不是的话,就直接返回parameter了。如果不清楚为什么设计者要这样子做不要紧,笔者这个时候也不知道为什么。所以笔者只要记得他做了什么。rowbounds类型变理rowbounds一般用于分页。默认是0到2147483647值,相信这个够你用了吧。resulthandler是用于处理返回的结果,这里直接就不要处理返回的结果了。所以笔者就不用讲了。

baseexecutor类:

 public <e> list<e> query(mappedstatement ms, object parameter, rowbounds rowbounds, resulthandler resulthandler) throws sqlexception {
  boundsql boundsql = ms.getboundsql(parameter);
  cachekey key = createcachekey(ms, parameter, rowbounds, boundsql);
  return query(ms, parameter, rowbounds, resulthandler, key, boundsql);
 }

类似于simpleexecutor这样子类并不是直接的继承了executor类。而是通过baseexecutor类这一层之后到继承executor类。所以query方法调用的时候并不是调用simpleexecutor类的。而是调用baseexecutor类的。当然你从simpleexecutor类也找不到query方法。显然是经过baseexecutor类进行处理相关的信息之后,在去调用executor子类的doquery方法。所以我们可以找到simpleexecutor类的doquery方法。这个过程笔者就不想细说。笔者主要目地还是引导大家去看的。

simpleexecutor类:

public <e> list<e> doquery(mappedstatement ms, object parameter, rowbounds rowbounds, resulthandler resulthandler, boundsql boundsql) throws sqlexception {
  statement stmt = null;
  try {
   configuration configuration = ms.getconfiguration();
   statementhandler handler = configuration.newstatementhandler(wrapper, ms, parameter, rowbounds, resulthandler, boundsql);
   stmt = preparestatement(handler, ms.getstatementlog());
   return handler.<e>query(stmt, resulthandler) ; 
  } finally {
   closestatement(stmt);
  }
 }

  从源码上来看笔者只认识俩个类一个是configuration类和statement类。statement类是属于jdbc的知识点。configuration类是属于mybatis框架的配置信息部分。意思就是通过mappedstatement获得configuration类的信息。在通过configuration类新建statementhandler接口实例。而statementhandler接口实例就是用来处理生成statement类的。很明显就是执行sql语句就是在statementhandler接口实例里面。

笔者来一个小结:动态代理的方式事实上最后还是动用sqlsession接口实例的方法。所以只有了解了sqlsession接口实例的方法就是可以进一步深入。而sqlsession接口实例执行方法的过程中又会去执行executor类的方法。而关于configuration类的作用可以说是任务时候都有可以初动用。当前最后的任务暂时是交给了executor类的子类。

好了。到了这里面,关于sqlsession接口和executor类的作用就有一个大概的像想空间。当然只望一下就明白sqlsession接口和executor类的话,笔者觉得有一点难。至少笔者没有这样子的能力。在笔者看来sqlsession接口和executor类的工作在doquery方法的时候,就已经圆完的结束了。虽然笔者并没有说出sqlsession接口和executor类的作用。主要还是靠你们自己去理解了。接下就来就是了解一下statementhandler接口的作用。

以上所述是小编给大家介绍的mybatis 源码分析 之sqlsession接口和executor类,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网