热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

mybatis随笔五之Executor

在上一篇文章我们分析到了mapper接口方法的实现实际上是交由代理类来实现的,并最终调用Executor来查询,接下来我们对executor.query(ms,wrapCollection(para
在上一篇文章我们分析到了mapper接口方法的实现实际上是交由代理类来实现的,并最终调用Executor来查询,接下来我们对
executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER)这个方法进行分析。
@Override
public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql
= ms.getBoundSql(parameterObject);
CacheKey key
= createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
ms.getBoundSql内部调用RawSqlSource的getBoundSql方法,该方法又调用了StaticSqlSource的getBoundSql方法,并在该方法内部初始化了一个BoundSql对象,如下是BoundSql的参数
  private String sql;   //需要执行的sql语句
private List parameterMappings; //参数与数据库列的对应关系
private Object parameterObject; //查询传递的参数
private Map additionalParameters;
private MetaObject metaParameters;
createCacheKey是调用的BaseExecutor方法根据mappedStatement的id,rowBounds的offset、limit值、要执行的sql语句、传递的参数、environment的id来创建cacheKey。
在query的时候查看是否有cache,如果有则使用cache结果,否则使用内部delegate的query方法,这里跳转到了BaseExecutor的query方法,该方法内部又使用了
queryFromDatabase方法。
private  List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List
list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
list
= doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
}
finally {
localCache.removeObject(key);
}
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
方法比较简单将查询结果保存在chche中,调用doQuery方法,BaseExecutor的doQuery方法是个抽象方法,因此这里实际使用的是子类SimpleExecutor的doQuery方法
 @Override
public List 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.query(stmt, resultHandler);
}
finally {
closeStatement(stmt);
}
}
我们先看看newStatementHandler这个方法,这个方法主要做了两件事情,实例化了一个RoutingStatementHandler对象,将拦截目标是statementHandler的拦截器构成拦截链。
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler
= new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler
= (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
RoutingStatementHandler采用的是装饰设计模式,内部delegate委托的是PreparedStatementHandler对象,因此它的构造方法内部去创建了一个PreparedStatementHandler对象
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.cOnfiguration= mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;

this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();

if (boundSql == null) { // issue #435, get the key before calculating the statement
generateKeys(parameterObject);
boundSql
= mappedStatement.getBoundSql(parameterObject);
}

this.boundSql = boundSql;

this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
构建的过程中也初始化了parameterHandler、resultSetHandler两个对象,顾名思义一个是用来处理参数的一个是用来处理结果的。
所以在创建StatementHandler的同时其余两个handler也被创建出来了。
接下来使用prepareStatement来构建参数。
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection
= getConnection(statementLog);
stmt
= handler.prepare(connection);
handler.parameterize(stmt);
return stmt;
}
在这个方法内部,我们最关注的是倒数二、三句。
handler.prepare类似mapper交由statementHandler的代理对象来执行,若没有针对其的拦截方法则还是调用RoutingStatementHandler的prepare方法。
public Statement prepare(Connection connection) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement
= null;
try {
statement
= instantiateStatement(connection);
setStatementTimeout(statement);
setFetchSize(statement);
return statement;
}
catch (SQLException e) {
closeStatement(statement);
throw e;
}
catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
这里主要做了几件事:返回preparedStatement对象、设置查询超时时间、设置每次批量返回的结果行数。
handler.parameterize(stmt)方法类似也是交由statementHandler的代理对象来执行,最终也使用RoutingStatementHandler的parameterize方法。
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
在这个方法里主要是根据定义的入参的javaType、jdbcType类型来选择合适的typeHandler来设置参数,因为我们使用的是long类型,因此typeHandler使用的是LongTypeHandler。
这样我们就把preparedStatement所需的参数全部填充了,最终进入handler.query(stmt, resultHandler)方法。
query方法也会先调用拦截链的方法,最后使用RoutingStatementHandler的query方法。
@Override
public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps
= (PreparedStatement) statement;
ps.execute();
return resultSetHandler. handleResultSets(ps);
}

 





  

 





推荐阅读
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有