ibatis学习四---执行流程浅析
首先看一段最基本的ibatis执行代码
1 public static void main(String[] args) throws IOException, SQLException{ 2 String config = "ibatis/SqlMapConfig.xml"; 3 Reader reader = Resources.getResourceAsReader(config); 4 SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); 5 List<Product> list = sqlMap.queryForList("getProductInfo", 1); 6 for(Product product : list){ 7 System.out.println(product); 8 } 9 }
首先使用Resources读取配置文件信息返回给reade,Resources的相关源码
1 public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {2 InputStream in = null;3 if (loader != null) in = loader.getResourceAsStream(resource);4 if (in == null) in = ClassLoader.getSystemResourceAsStream(resource);5 if (in == null) throw new IOException("Could not find resource " + resource);6 return in;7 }8 9 public static Reader getResourceAsReader(String resource) throws IOException { 10 Reader reader; 11 if (charset == null) { 12 reader = new InputStreamReader(getResourceAsStream(resource)); 13 } else { 14 reader = new InputStreamReader(getResourceAsStream(resource), charset); 15 } 16 17 return reader; 18 }
就是调用Resources的静态方法getResourceAsReader,该方法调用getResourceAsStream方法,ClassLoader根据配置文件的路径返回InputStream,找不到文件则抛出异常。getResourceAsReader方法根据返回的InputStream返回Reader,若指定了编码类型则转换为相应编码。
SqlMapClientBuilder类的buildSqlMapClient方法代码
1 public static SqlMapClient buildSqlMapClient(Reader reader) { 2 // return new XmlSqlMapClientBuilder().buildSqlMap(reader); 3 return new SqlMapConfigParser().parse(reader); 4 }
SqlMapConfigParser类根据配置文件解析参数返回
下面看一下ibatis内部SqlMapClient的实现过程。
SqlMapClientImpl的部分代码
1 public class SqlMapClientImpl implements SqlMapClient, ExtendedSqlMapClient {2 3 private static final Log log = LogFactory.getLog(SqlMapClientImpl.class);4 5 /**6 * Delegate for SQL execution7 */8 public SqlMapExecutorDelegate delegate;9 10 protected ThreadLocal localSqlMapSession = new ThreadLocal(); 11 12 /** 13 * Constructor to supply a delegate 14 * 15 * @param delegate - the delegate 16 */ 17 public SqlMapClientImpl(SqlMapExecutorDelegate delegate) { 18 this.delegate = delegate; 19 } 20 21 22 protected SqlMapSessionImpl getLocalSqlMapSession() { 23 SqlMapSessionImpl sqlMapSession = (SqlMapSessionImpl) localSqlMapSession.get(); 24 if (sqlMapSession == null || sqlMapSession.isClosed()) { 25 sqlMapSession = new SqlMapSessionImpl(this); 26 localSqlMapSession.set(sqlMapSession); 27 } 28 return sqlMapSession; 29 } 30 31 public List queryForList(String id, Object paramObject) throws SQLException { 32 return getLocalSqlMapSession().queryForList(id, paramObject); 33 } 34 35 public List queryForList(String id) throws SQLException { 36 return getLocalSqlMapSession().queryForList(id); 37 } 38 39 public List queryForList(String id, Object paramObject, int skip, int max) throws SQLException { 40 return getLocalSqlMapSession().queryForList(id, paramObject, skip, max); 41 } 42 43 public List queryForList(String id, int skip, int max) throws SQLException { 44 return getLocalSqlMapSession().queryForList(id, skip, max); 45 } 46 }
由代码中看出,ThreadLocal 的localSqlMapSession中存储着SqlMapSessionImpl实例,queryForList方法实际是使用本线程内的SqlMapSessionImpl的queryForList方法。
SqlMapSessionImpl的部分代码
1 public class SqlMapSessionImpl implements SqlMapSession {2 3 protected SqlMapExecutorDelegate delegate;4 protected SessionScope sessionScope;5 protected boolean closed;6 7 /**8 * Constructor9 * 10 * @param client - the client that will use the session 11 */ 12 public SqlMapSessionImpl(SqlMapClientImpl client) { 13 this.delegate = client.getDelegate(); 14 this.sessionScope = this.delegate.beginSessionScope(); 15 this.sessionScope.setSqlMapClient(client); 16 this.sessionScope.setSqlMapExecutor(client); 17 this.sessionScope.setSqlMapTxMgr(client); 18 this.closed = false; 19 } 20 21 public List queryForList(String id, Object paramObject) throws SQLException { 22 return delegate.queryForList(sessionScope, id, paramObject); 23 } 24 25 public List queryForList(String id) throws SQLException { 26 return queryForList(id, null); 27 } 28 29 public List queryForList(String id, Object paramObject, int skip, int max) throws SQLException { 30 return delegate.queryForList(sessionScope, id, paramObject, skip, max); 31 } 32 33 public List queryForList(String id, int skip, int max) throws SQLException { 34 return queryForList(id, null, skip, max); 35 } 36 } 37 38
SqlMapSessionImpl中有一个delegate代理,它的queryForList方法中调用delegate的queryForList方法。
SqlMapExecutorDelegate类比较复杂,它实现了执行数据库操作的完整环境,包括缓存、MappedStatement、参数映射ParameterMap、返回结果ResultMap、事务管理、增删改成操作。源代码有900+行,只给出部分代码,完整代码参考ibatis源码包中SqlMapExecutorDelegate.java文件。
1 public class SqlMapExecutorDelegate { 2 3 private static final Probe PROBE = ProbeFactory.getProbe(); 4 5 private boolean lazyLoadingEnabled; 6 private boolean cacheModelsEnabled; 7 private boolean enhancementEnabled; 8 private boolean useColumnLabel = true; 9 private boolean forceMultipleResultSetSupport; 10 11 private TransactionManager txManager; 12 13 private HashMap mappedStatements; 14 private HashMap cacheModels; 15 private HashMap resultMaps; 16 private HashMap parameterMaps; 17 18 protected SqlExecutor sqlExecutor; 19 private TypeHandlerFactory typeHandlerFactory; 20 private DataExchangeFactory dataExchangeFactory; 21 22 private ResultObjectFactory resultObjectFactory; 23 private boolean statementCacheEnabled; 24 25 /** 26 * Default constructor 27 */ 28 public SqlMapExecutorDelegate() { 29 mappedStatements = new HashMap(); 30 cacheModels = new HashMap(); 31 resultMaps = new HashMap(); 32 parameterMaps = new HashMap(); 33 34 sqlExecutor = new SqlExecutor(); 35 typeHandlerFactory = new TypeHandlerFactory(); 36 dataExchangeFactory = new DataExchangeFactory(typeHandlerFactory); 37 } 38 39 public List queryForList(SessionScope sessionScope, String id, Object paramObject) throws SQLException { 40 return queryForList(sessionScope, id, paramObject, SqlExecutor.NO_SKIPPED_RESULTS, SqlExecutor.NO_MAXIMUM_RESULTS); 41 } 42 43 public List queryForList(SessionScope sessionScope, String id, Object paramObject, int skip, int max) throws SQLException { 44 List list = null; 45 46 MappedStatement ms = getMappedStatement(id); 47 Transaction trans = getTransaction(sessionScope); 48 boolean autoStart = trans == null; 49 50 try { 51 trans = autoStartTransaction(sessionScope, autoStart, trans); 52 53 StatementScope statementScope = beginStatementScope(sessionScope, ms); 54 try { 55 list = ms.executeQueryForList(statementScope, trans, paramObject, skip, max); 56 } finally { 57 endStatementScope(statementScope); 58 } 59 60 autoCommitTransaction(sessionScope, autoStart); 61 } finally { 62 autoEndTransaction(sessionScope, autoStart); 63 } 64 65 return list; 66 } 67 }
获取sessionScope、statementScope、MappedStatement、Transaction等相关实例,核心是调用MappedStatement的executeQueryForList方法:list = ms.executeQueryForList(statementScope, trans, paramObject, skip, max);
查看一下MappedStatement相关代码
1 public class MappedStatement { 2 private String id; 3 private Integer resultSetType; 4 private Integer fetchSize; 5 private ResultMap resultMap; 6 private ParameterMap parameterMap; 7 private Class parameterClass; 8 private Sql sql; 9 private int baseCacheKey; 10 private SqlMapClientImpl sqlMapClient; 11 private Integer timeout; 12 private ResultMap[] additionalResultMaps = new ResultMap[0]; 13 private List executeListeners = new ArrayList(); 14 private String resource; 15 16 public List executeQueryForList(StatementScope statementScope, Transaction trans, Object parameterObject, int skipResults, int maxResults) 17 throws SQLException { 18 try { 19 DefaultRowHandler rowHandler = new DefaultRowHandler(); 20 executeQueryWithCallback(statementScope, trans.getConnection(), parameterObject, null, rowHandler, skipResults, maxResults); 21 return rowHandler.getList(); 22 } catch (TransactionException e) { 23 throw new NestedSQLException("Error getting Connection from Transaction. Cause: " + e, e); 24 } 25 } 26 27 protected void executeQueryWithCallback(StatementScope statementScope, Connection conn, Object parameterObject, Object resultObject, RowHandler rowHandler, int skipResults, int maxResults) 28 throws SQLException { 29 ErrorContext errorContext = statementScope.getErrorContext(); 30 errorContext.setActivity("preparing the mapped statement for execution"); 31 errorContext.setObjectId(this.getId()); 32 errorContext.setResource(this.getResource()); 33 34 try { 35 parameterObject = validateParameter(parameterObject); 36 37 Sql sql = getSql(); 38 39 errorContext.setMoreInfo("Check the parameter map."); 40 ParameterMap parameterMap = sql.getParameterMap(statementScope, parameterObject); 41 42 errorContext.setMoreInfo("Check the result map."); 43 ResultMap resultMap = sql.getResultMap(statementScope, parameterObject); 44 45 statementScope.setResultMap(resultMap); 46 statementScope.setParameterMap(parameterMap); 47 48 errorContext.setMoreInfo("Check the parameter map."); 49 Object[] parameters = parameterMap.getParameterObjectValues(statementScope, parameterObject); 50 51 errorContext.setMoreInfo("Check the SQL statement."); 52 String sqlString = sql.getSql(statementScope, parameterObject); 53 54 errorContext.setActivity("executing mapped statement"); 55 errorContext.setMoreInfo("Check the SQL statement or the result map."); 56 RowHandlerCallback callback = new RowHandlerCallback(resultMap, resultObject, rowHandler); 57 sqlExecuteQuery(statementScope, conn, sqlString, parameters, skipResults, maxResults, callback); 58 59 errorContext.setMoreInfo("Check the output parameters."); 60 if (parameterObject != null) { 61 postProcessParameterObject(statementScope, parameterObject, parameters); 62 } 63 64 errorContext.reset(); 65 sql.cleanup(statementScope); 66 notifyListeners(); 67 } catch (SQLException e) { 68 errorContext.setCause(e); 69 throw new NestedSQLException(errorContext.toString(), e.getSQLState(), e.getErrorCode(), e); 70 } catch (Exception e) { 71 errorContext.setCause(e); 72 throw new NestedSQLException(errorContext.toString(), e); 73 } 74 } 75 }
protected void sqlExecuteQuery(StatementScope statementScope, Connection conn, String sqlString, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {getSqlExecutor().executeQuery(statementScope, conn, sqlString, parameters, skipResults, maxResults, callback);}
最终由SqlExecutor实现sql操作,实现代码
1 /** 2 * Long form of the method to execute a query 3 * 4 * @param statementScope - the request scope 5 * @param conn - the database connection 6 * @param sql - the SQL statement to execute 7 * @param parameters - the parameters for the statement 8 * @param skipResults - the number of results to skip 9 * @param maxResults - the maximum number of results to return 10 * @param callback - the row handler for the query 11 * @throws SQLException - if the query fails 12 */ 13 public void executeQuery(StatementScope statementScope, Connection conn, String sql, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException { 14 ErrorContext errorContext = statementScope.getErrorContext(); 15 errorContext.setActivity("executing query"); 16 errorContext.setObjectId(sql); 17 PreparedStatement ps = null; 18 ResultSet rs = null; 19 setupResultObjectFactory(statementScope); 20 try { 21 errorContext.setMoreInfo("Check the SQL Statement (preparation failed)."); 22 Integer rsType = statementScope.getStatement().getResultSetType(); 23 if (rsType != null) { 24 ps = prepareStatement(statementScope.getSession(), conn, sql, rsType); 25 } else { 26 ps = prepareStatement(statementScope.getSession(), conn, sql); 27 } 28 setStatementTimeout(statementScope.getStatement(), ps); 29 Integer fetchSize = statementScope.getStatement().getFetchSize(); 30 if (fetchSize != null) { 31 ps.setFetchSize(fetchSize.intValue()); 32 } 33 errorContext.setMoreInfo("Check the parameters (set parameters failed)."); 34 statementScope.getParameterMap().setParameters(statementScope, ps, parameters); 35 errorContext.setMoreInfo("Check the statement (query failed)."); 36 ps.execute(); 37 errorContext.setMoreInfo("Check the results (failed to retrieve results)."); 38 39 // Begin ResultSet Handling 40 rs = handleMultipleResults(ps, statementScope, skipResults, maxResults, callback); 41 // End ResultSet Handling 42 } finally { 43 try { 44 closeResultSet(rs); 45 } finally { 46 closeStatement(statementScope.getSession(), ps); 47 } 48 } 49 50 }
handleMuiltipleResults方法代码
1 private ResultSet handleMultipleResults(PreparedStatement ps, StatementScope statementScope, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException { 2 ResultSet rs; 3 rs = getFirstResultSet(statementScope, ps); 4 if (rs != null) { 5 handleResults(statementScope, rs, skipResults, maxResults, callback); 6 } 7 8 // Multiple ResultSet handling 9 if (callback.getRowHandler() instanceof DefaultRowHandler) { 10 MappedStatement statement = statementScope.getStatement(); 11 DefaultRowHandler defaultRowHandler = ((DefaultRowHandler) callback.getRowHandler()); 12 if (statement.hasMultipleResultMaps()) { 13 List multipleResults = new ArrayList(); 14 multipleResults.add(defaultRowHandler.getList()); 15 ResultMap[] resultMaps = statement.getAdditionalResultMaps(); 16 int i = 0; 17 while (moveToNextResultsSafely(statementScope, ps)) { 18 if (i >= resultMaps.length) break; 19 ResultMap rm = resultMaps[i]; 20 statementScope.setResultMap(rm); 21 rs = ps.getResultSet(); 22 DefaultRowHandler rh = new DefaultRowHandler(); 23 handleResults(statementScope, rs, skipResults, maxResults, new RowHandlerCallback(rm, null, rh)); 24 multipleResults.add(rh.getList()); 25 i++; 26 } 27 defaultRowHandler.setList(multipleResults); 28 statementScope.setResultMap(statement.getResultMap()); 29 } else { 30 while (moveToNextResultsSafely(statementScope, ps)) ; 31 } 32 } 33 // End additional ResultSet handling 34 return rs; 35 }
转载于:https://www.cnblogs.com/waimai/archive/2013/01/06/2847460.html
ibatis学习四---执行流程浅析相关推荐
- java 内存分配实例_java学习(四) —— 内存分配浅析
前言 java中有很多类型的变量.静态变量.全局变量及对象等,这些变量在java运行的时候到底是如何分配内存的呢?接下来有必要对此进行一些探究. 基本知识概念: (1)寄存器:最快的存储区, 由编译器 ...
- ClickHouse Query执行流程浅析
语法树生成及执行涉及的UML图 HTTP Handler 接收Query请求 调用 Interpreters::executeQuery.h::executeQuery(-) 调用 Interpret ...
- 内核启动流程分析(四)源码浅析
目录 kernel(四)源码浅析 建立工程 启动简析 head.s 入口点 查询处理器 查询机器ID 启动MMU 其他操作 start_kernel 处理命令行 分区 kernel(四)源码浅析 建立 ...
- {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证...
Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...
- 「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析
「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析 前言 一.我的开发环境 二.使用 Vue CLI (Vue 脚手架)快速搭建项目 三.初始项目的目录结构 ...
- scala语言的底层是java实现的_Scala学习笔记一(与Java、Jvm的关系以及程序执行流程分析)...
一.Scala语言与Java.Jvm的关系分析 Scala语言是马丁奥德斯基接触Java语言后,针对Java语言的特点,将函数式编程语言的特点融合到Java中,由此发明的.Scala语言和Java语言 ...
- mybatis源码学习篇之——执行流程分析
前言 在正式学习mybatis框架源码之前,需要先弄懂几个问题?myabtis框架是什么?为什么需要mybatis框架?使用mybatis框架带来的好处是什么? 回答这几个问题之前,我们先来看一下,之 ...
- MySql 学习笔记-Mysql架构介绍与查询sql执行流程
最近花了99元大洋在极客时间 买了 MySQL 实战45讲.学习的同时留下点笔记.该内容仅仅是个人总结笔记,如有涉及版权还请告知. MySql 的简介 MySQL是一个关系型数据库管理系统,由瑞典My ...
- python编程案例教程第四章_Python编程入门-第四章 流程控制 -学习笔记
第四章 流程控制 一.布尔逻辑 *在Python中,用True和False表示真值.一般使用4个主要的逻辑运算符来组合形成布尔值:not\and\or\==. 如: False==False #Tru ...
- 讲mysql执行流程书籍_MySQL 基础架构 1. 一条SQL查询语句的执行过程(个人学习笔记)...
MySQL的逻辑架构图: MySQL 大体分为 "server 层" 和 "存储引擎层" 两部分: Server 层 包括 连接器.查询缓存.分析器.优化器.执 ...
最新文章
- 学计算机专业需要考的证有哪些科目,自考计算机专业的考试科目有哪些?
- 微信公众号监听返回按钮问题解决
- tomcat7+nginx+memcached 配置tomcat 集群以及负载均衡
- java调用cmd关闭excel,java 调用 windows 的 cmd 命令
- 认识 sun.misc.Unsafe
- BFS Codeforces Beta Round #94 (Div. 2 Only) C. Statues
- 【以前的空间】网络流合集
- 职称计算机execl试题,职称计算机考试EXCEL操作题
- latex参考文献编译不成功
- win7计算机文件扩展名,win7显示文件后缀名的扩展名方法
- 阿米洛键盘取消win_阿米洛键盘驱动|阿米洛樱花键盘驱动下载v1.0官方版 - 欧普软件下载...
- 田园综合体建设指导手册
- SpringBoot企业微信点餐系统
- ECCV2022 | 开源:基于可分离级联查找表的实时图像增强方法
- 怎么把html转成mp4,怎么把其他视频格式转成常用的mp4形式?
- 蓝桥杯单片机第11届国赛程序题参考答案
- 河南本科计算机科学与技术排名,河南计算机科学与技术专业大学排名
- python 的几个源生方法
- JavaScript数组遍历5 every方法
- vue中npm引入editor.md编辑器插件
热门文章
- 公务员因微信办公被处分!如何避免微信办公导致信息泄密?
- codeforces 455D Serega and Fun
- 函数命名空间,函数的名字
- xpath提取目录下所有标签内的内容,递归 //text()
- About “condition variables”
- 巧用G6FTPServer账号***台湾某图书服务器
- 数据--第35课 - 创建二叉树
- Oracle Study之-- enq:SQ contention等待事件
- Python中List,tuple,Dictionary之间的区别
- android动态加载.so,实现动态库升级