首先看一段最基本的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学习四---执行流程浅析相关推荐

  1. java 内存分配实例_java学习(四) —— 内存分配浅析

    前言 java中有很多类型的变量.静态变量.全局变量及对象等,这些变量在java运行的时候到底是如何分配内存的呢?接下来有必要对此进行一些探究. 基本知识概念: (1)寄存器:最快的存储区, 由编译器 ...

  2. ClickHouse Query执行流程浅析

    语法树生成及执行涉及的UML图 HTTP Handler 接收Query请求 调用 Interpreters::executeQuery.h::executeQuery(-) 调用 Interpret ...

  3. 内核启动流程分析(四)源码浅析

    目录 kernel(四)源码浅析 建立工程 启动简析 head.s 入口点 查询处理器 查询机器ID 启动MMU 其他操作 start_kernel 处理命令行 分区 kernel(四)源码浅析 建立 ...

  4. {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证...

    Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...

  5. 「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析

    「Vue 学习笔记 1」Vue 项目快速搭建,初始项目各个文件夹作用介绍和启动代码执行流程分析 前言 一.我的开发环境 二.使用 Vue CLI (Vue 脚手架)快速搭建项目 三.初始项目的目录结构 ...

  6. scala语言的底层是java实现的_Scala学习笔记一(与Java、Jvm的关系以及程序执行流程分析)...

    一.Scala语言与Java.Jvm的关系分析 Scala语言是马丁奥德斯基接触Java语言后,针对Java语言的特点,将函数式编程语言的特点融合到Java中,由此发明的.Scala语言和Java语言 ...

  7. mybatis源码学习篇之——执行流程分析

    前言 在正式学习mybatis框架源码之前,需要先弄懂几个问题?myabtis框架是什么?为什么需要mybatis框架?使用mybatis框架带来的好处是什么? 回答这几个问题之前,我们先来看一下,之 ...

  8. MySql 学习笔记-Mysql架构介绍与查询sql执行流程

    最近花了99元大洋在极客时间 买了 MySQL 实战45讲.学习的同时留下点笔记.该内容仅仅是个人总结笔记,如有涉及版权还请告知. MySql 的简介 MySQL是一个关系型数据库管理系统,由瑞典My ...

  9. python编程案例教程第四章_Python编程入门-第四章 流程控制 -学习笔记

    第四章 流程控制 一.布尔逻辑 *在Python中,用True和False表示真值.一般使用4个主要的逻辑运算符来组合形成布尔值:not\and\or\==. 如: False==False #Tru ...

  10. 讲mysql执行流程书籍_MySQL 基础架构 1. 一条SQL查询语句的执行过程(个人学习笔记)...

    MySQL的逻辑架构图: MySQL 大体分为 "server 层" 和 "存储引擎层" 两部分: Server 层 包括 连接器.查询缓存.分析器.优化器.执 ...

最新文章

  1. 学计算机专业需要考的证有哪些科目,自考计算机专业的考试科目有哪些?
  2. 微信公众号监听返回按钮问题解决
  3. tomcat7+nginx+memcached 配置tomcat 集群以及负载均衡
  4. java调用cmd关闭excel,java 调用 windows 的 cmd 命令
  5. 认识 sun.misc.Unsafe
  6. BFS Codeforces Beta Round #94 (Div. 2 Only) C. Statues
  7. 【以前的空间】网络流合集
  8. 职称计算机execl试题,职称计算机考试EXCEL操作题
  9. latex参考文献编译不成功
  10. win7计算机文件扩展名,win7显示文件后缀名的扩展名方法
  11. 阿米洛键盘取消win_阿米洛键盘驱动|阿米洛樱花键盘驱动下载v1.0官方版 - 欧普软件下载...
  12. 田园综合体建设指导手册
  13. SpringBoot企业微信点餐系统
  14. ECCV2022 | 开源:基于可分离级联查找表的实时图像增强方法
  15. 怎么把html转成mp4,怎么把其他视频格式转成常用的mp4形式?
  16. 蓝桥杯单片机第11届国赛程序题参考答案
  17. 河南本科计算机科学与技术排名,河南计算机科学与技术专业大学排名
  18. python 的几个源生方法
  19. JavaScript数组遍历5 every方法
  20. vue中npm引入editor.md编辑器插件

热门文章

  1. 公务员因微信办公被处分!如何避免微信办公导致信息泄密?
  2. codeforces 455D Serega and Fun
  3. 函数命名空间,函数的名字
  4. xpath提取目录下所有标签内的内容,递归 //text()
  5. About “condition variables”
  6. 巧用G6FTPServer账号***台湾某图书服务器
  7. 数据--第35课 - 创建二叉树
  8. Oracle Study之-- enq:SQ contention等待事件
  9. Python中List,tuple,Dictionary之间的区别
  10. android动态加载.so,实现动态库升级