摘录自:http://blog.csdn.net/y172158950/article/details/16982123

在helloworld(1)中,分析了insert一条数据的流程,现在分析下源码:

  1. public static void main(String args[]) throws IOException {
  2. String resource = "com/test/configuration.xml";//获得xml(Mybatis)数据库连接的连接
  3. Reader reader = Resources.getResourceAsReader(resource);//读取里面的文件
  4. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
  5. .build(reader);//创建session工厂
  6. SqlSession session = sessionFactory.openSession();//打开session
  7. new Test1().insert(session);
  8. }

1. XML文件资源的获取

a)包路径:org.apache.ibatis.io

b)Resources类:定义了一系列的静态方法,用于获取资源(ClassLoader,URL,InputStream,Read,File,Properties,Charset)

c)我们用到的getResourceAsReader,getResourceAsStream方法

  1. <p>    public static Reader getResourceAsReader(String resource)
  2. throws IOException
  3. {
  4. Reader reader;</p><p>·       //利用InputStream构造Reader
  5. if(charset == null)
  6. reader = new InputStreamReader(getResourceAsStream(resource));
  7. else
  8. reader = new InputStreamReader(getResourceAsStream(resource), charset);
  9. return reader;
  10. }</p><p>   </p><p>    public static InputStream getResourceAsStream(String resource)
  11. throws IOException
  12. {</p><p>        //调用重载方法
  13. return getResourceAsStream(null, resource);
  14. }</p><p> </p><p>    public static InputStream getResourceAsStream(ClassLoader loader, String resource)
  15. throws IOException
  16. {</p><p>        //调用ClassLoaderWrapper类的方法,利用ClassLoader获取资源
  17. InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
  18. if(in == null)
  19. throw new IOException((new StringBuilder()).append("Could not find resource ").append(resource).toString());
  20. else
  21. return in;
  22. }</p>

d)ClassLoaderWrapper类:封装了一个ClassLoader数组,通过ClassLoader获取资源

e)我们用到的getResourceAsStream,getClassLoaders方法

  1. public InputStream getResourceAsStream(String resource, ClassLoader classLoader)
  2. {
  3. return getResourceAsStream(resource, getClassLoaders(classLoader));
  4. }
  5. ClassLoader[] getClassLoaders(ClassLoader classLoader)
  6. {
  7. return (new ClassLoader[] {  //构建新的ClassLoader列表,包含用户创建及默认
  8. classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(),           systemClassLoader});
  9. }
  10. InputStream getResourceAsStream(String resource, ClassLoader classLoader[])
  11. {
  12. ClassLoader arr$[] = classLoader;
  13. int len$ = arr$.length;
  14. for(int i$ = 0; i$ < len$; i$++)    //遍历ClassLoader数组,当某一个Loader成功构建资源则返回
  15. {
  16. ClassLoader cl = arr$[i$];
  17. if(null == cl)
  18. continue;
  19. InputStream returnValue = cl.getResourceAsStream(resource);
  20. if(null == returnValue)
  21. returnValue = cl.getResourceAsStream((new StringBuilder()).append("/").append(resource).toString());
  22. if(null != returnValue)
  23. return returnValue;
  24. }
  25. return null;
  26. }

2. 构建SqlSessionFactory,初始化资源

a) SqlSessionFactory接口介绍

  1. public interface SqlSessionFactory
  2. {
  3. //定义了一系列获取Session的方法,获取Configuration的方法
  4. public abstract SqlSession openSession();
  5. public abstract SqlSession openSession(boolean flag);
  6. public abstract SqlSession openSession(Connection connection);
  7. public abstract SqlSession openSession(TransactionIsolationLevel transactionisolationlevel);
  8. public abstract SqlSession openSession(ExecutorType executortype);
  9. public abstract SqlSession openSession(ExecutorType executortype, boolean flag);
  10. public abstract SqlSession openSession(ExecutorType executortype, TransactionIsolationLevel transactionisolationlevel);
  11. public abstract SqlSession openSession(ExecutorType executortype, Connection connection);
  12. public abstract Configuration getConfiguration();
  13. }

b) SqlSessionFactory接口构建

i. SqlSessionFactoryBuilder类:构建SqlSessionFactory

ii. 我们使用的方法:build

  1. public SqlSessionFactory build(Reader reader)
  2. {
  3. //调用重载方法
  4. return build(reader, null, null);
  5. }
  6. public SqlSessionFactory build(Reader reader, String environment, Properties properties)
  7. {
  8. try
  9. {
  10. SqlSessionFactory sqlsessionfactory;
  11. try
  12. {
  13. //根据reader封装XMLConfig相关信息
  14. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
  15. //调用重载方法
  16. sqlsessionfactory = build(parser.parse());
  17. }
  18. catch(Exception e)
  19. {
  20. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  21. }
  22. return sqlsessionfactory;
  23. }
  24. finally
  25. {
  26. ErrorContext.instance().reset();
  27. try
  28. {
  29. reader.close();
  30. }
  31. catch(IOException e) { }
  32. }
  33. }
  34. public SqlSessionFactory build(Configuration config)
  35. {
  36. //依据配置信息构建默认的SqlSessionFactory实现
  37. return new DefaultSqlSessionFactory(config);
  38. }

c) XMLConfigBuilder类:解析XML配置文件

i. 用到的主要方法:parse,parseConfiguration(就是按XML结构顺序解析,分别获取配置[SAX解析]);将数据封装到父类的configuration对象中

  1. public Configuration parse()
  2. {
  3. if(parsed)
  4. {
  5. throw new BuilderException("Each MapperConfigParser can only be used once.");
  6. } else
  7. {
  8. parsed = true;
  9. parseConfiguration(parser.evalNode("/configuration"));   //XML文件的根目录
  10. return configuration;
  11. }
  12. }
  13. private void parseConfiguration(XNode root)
  14. {
  15. try
  16. {
  17. typeAliasesElement(root.evalNode("typeAliases"));    //解析typeAliases
  18. pluginElement(root.evalNode("plugins"));
  19. objectFactoryElement(root.evalNode("objectFactory"));
  20. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
  21. propertiesElement(root.evalNode("properties"));
  22. settingsElement(root.evalNode("settings"));
  23. environmentsElement(root.evalNode("environments"));   //数据库配置
  24. typeHandlerElement(root.evalNode("typeHandlers"));
  25. mapperElement(root.evalNode("mappers"));    //解析sql语句配置文件
  26. }
  27. catch(Exception e)
  28. {
  29. throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);
  30. }
  31. }

d)Configuration类:基本就是封装一系列的数据;看一下成员变量

  1. protected Environment environment;
  2. protected boolean lazyLoadingEnabled;
  3. protected boolean aggressiveLazyLoading;
  4. protected boolean multipleResultSetsEnabled;
  5. protected boolean useGeneratedKeys;
  6. protected boolean useColumnLabel;
  7. protected boolean cacheEnabled;
  8. protected Integer defaultStatementTimeout;
  9. protected ExecutorType defaultExecutorType;
  10. protected AutoMappingBehavior autoMappingBehavior;
  11. protected Properties variables;
  12. protected ObjectFactory objectFactory;
  13. protected ObjectWrapperFactory objectWrapperFactory;
  14. protected MapperRegistry mapperRegistry;
  15. protected final InterceptorChain interceptorChain;
  16. protected final TypeHandlerRegistry typeHandlerRegistry;
  17. protected final TypeAliasRegistry typeAliasRegistry;
  18. protected final Map mappedStatements;
  19. protected final Map caches;
  20. protected final Map resultMaps;
  21. protected final Map parameterMaps;
  22. protected final Map keyGenerators;
  23. protected final Set loadedResources;
  24. protected final Map sqlFragments;
  25. protected final Collection incompleteStatements;
  26. protected final Collection incompleteCacheRefs;
  27. protected final Map cacheRefMap;

e)DefaultSqlSessionFactory类:SqlSessionFactory接口实现类,并持有一个Configuration对象;我们实现获取SqlSeesion对象应用的此类的方法。

3. 回过头来,再看看SqlSession session = sessionFactory.openSession();这行代码的实现

  1. public SqlSession openSession()
  2. {
  3. return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  4. }
  5. private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
  6. {
  7. Connection connection = null;
  8. try
  9. {
  10. DefaultSqlSession defaultsqlsession;
  11. try
  12. {
  13. Environment environment = configuration.getEnvironment();
  14. //获取javax.sql.DataSource
  15. DataSource dataSource = getDataSourceFromEnvironment(environment);
  16. TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
  17. //获取java.sql.Connection
  18. connection = dataSource.getConnection();
  19. if(level != null)
  20. connection.setTransactionIsolation(level.getLevel());
  21. connection = wrapConnection(connection);
  22. //一系列的封装,把Connection包装成了DefaultSqlSession(SqlSession的实现类)
  23. org.apache.ibatis.transaction.Transaction tx = transactionFactory.newTransaction(connection, autoCommit);
  24. org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
  25. defaultsqlsession = new DefaultSqlSession(configuration, executor, autoCommit);
  26. }
  27. catch(Exception e)
  28. {
  29. closeConnection(connection);
  30. throw ExceptionFactory.wrapException((new StringBuilder()).append("Error opening session.  Cause: ").append(e).toString(), e);
  31. }
  32. return defaultsqlsession;
  33. }
  34. finally
  35. {
  36. ErrorContext.instance().reset();
  37. }
  38. }

4. insert数据的实现

  1. public int insert(String statement, Object parameter)
  2. {
  3. return update(statement, parameter);
  4. }
  5. public int update(String statement, Object parameter)
  6. {
  7. try
  8. {
  9. int i;
  10. try
  11. {
  12. dirty = true;
  13. //根据Mapper.xml配置文件中的id找到Sql语句
  14. org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
  15. //这个执行器是不是见过?构建DefaultSqlSession时传过来的
  16. // org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
  17. i = executor.update(ms, wrapCollection(parameter));
  18. }
  19. catch(Exception e)
  20. {
  21. throw ExceptionFactory.wrapException((new StringBuilder()).append("Error updating database.  Cause: ").append(e).toString(), e);
  22. }
  23. return i;
  24. }
  25. finally
  26. {
  27. ErrorContext.instance().reset();
  28. }
  29. }

a) 找一下executor,看看其update方法

i. 调用哪个executor?

  1. public Executor newExecutor(Transaction transaction, ExecutorType executorType)
  2. {
  3. executorType = executorType != null ? executorType : defaultExecutorType;  //我们使用的是默认的Type(SIMPLE)
  4. executorType = executorType != null ? executorType : ExecutorType.SIMPLE;
  5. Executor executor;
  6. if(ExecutorType.BATCH == executorType)
  7. executor = new BatchExecutor(this, transaction);
  8. else
  9. if(ExecutorType.REUSE == executorType)
  10. executor = new ReuseExecutor(this, transaction);
  11. else
  12. executor = new SimpleExecutor(this, transaction);
  13. if(cacheEnabled)
  14. executor = new CachingExecutor(executor);
  15. executor = (Executor)interceptorChain.pluginAll(executor);
  16. return executor;
  17. }

ii. SimpleExecutor的update方法实现

  1. //父类BaseExecutor的update方法,调用了doUpdate方法
  2. public int update(MappedStatement ms, Object parameter)
  3. throws SQLException
  4. {
  5. ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
  6. if(closed)
  7. {
  8. throw new ExecutorException("Executor was closed.");
  9. } else
  10. {
  11. clearLocalCache();
  12. return doUpdate(ms, parameter);
  13. }
  14. }
  15. //子类SimpleExecutor重写了doUpdate方法
  16. public int doUpdate(MappedStatement ms, Object parameter)
  17. throws SQLException
  18. {
  19. //java.sql.Statement
  20. Statement stmt = null;
  21. int i;
  22. try
  23. {
  24. Configuration configuration = ms.getConfiguration();
  25. StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null);
  26. //大概就是拼Sql,生成对应的Statement,执行Sql,封装数据了(这块比较复杂,下次再看了)
  27. stmt = prepareStatement(handler);
  28. i = handler.update(stmt);
  29. }
  30. finally
  31. {
  32. closeStatement(stmt);
  33. }
  34. return i;
  35. }

看了一回源码,也感觉高端大气上档次了,下次画个图

mybatis_helloworld(2)_源码的更多相关文章

  1. java画图程序_图片用字母画出来_源码发布_版本二

    在上一个版本:java画图程序_图片用字母画出来_源码发布 基础上,增加了图片同比例缩放,使得大像素图片可以很好地显示画在Notepad++中. 项目结构: 运行效果1: 原图:http://imag ...

  2. pygame系列_小球完全弹性碰撞游戏_源码下载

    之前做了一个基于python的tkinter的小球完全碰撞游戏: python开发_tkinter_小球完全弹性碰撞游戏_源码下载 今天利用业余时间,写了一个功能要强大一些的小球完全碰撞游戏: 游戏名 ...

  3. Django_Restframwork_APIVIEW视图_源码分析

    Django _VIEW视图_源码分析

  4. java画图程序_图片用字母画出来_源码发布

    在之前写了一篇blog:java画图程序_图片用字母画出来 主要是把一些调试的截图发布出来,现在程序调试我认为可以了(当然,你如果还想调试的话,也可以下载源码自己调试). 就把源码发布出来. 项目结构 ...

  5. 软件包管理_rpm命令管理_yum工具管理_文件归档压缩_源码包管理

    rpm命令管理软件 对于挂载的像U盘那种都会在midea目录下,但是会显示在桌面上 安装软件(i:install,v:verbose冗长的,h:human):rpm  -ivh  xxxx.rpm 安 ...

  6. bootstrap_栅格系统_响应式工具_源码分析

    -----------------------------------------------------------------------------margin 为负 ​使盒子重叠 ​等高 等高 ...

  7. QT_文本编辑器_源码下载

    源码下载: 链接: http://pan.baidu.com/s/1c21EVRy 密码: qub8 实现主要的功能有:新建,打开,保存,另存为,查找(查找的时候需要先将光标放到最下面位置才能查全,不 ...

  8. 『TensorFlow Internals』笔记_源码结构

    零.资料集合 知乎专栏:Bob学步 知乎提问:如何高效的学习 TensorFlow 代码?. 大佬刘光聪(Github,简书) 开源书:TensorFlow Internals,强烈推荐(本博客参考书 ...

  9. pygame系列_font游戏字体_源码下载

    在pygame游戏开发中,一个友好的UI中,漂亮的字体是少不了的 今天就给大伙带来有关pygame中字体的一些介绍说明 首先我们得判断一下我们的pygame中有没有font这个模块 if not py ...

随机推荐

  1. Android OpenGL ES 入门系列(二) --- 环境搭建

    转载请注明出处 本文出自Hansion的博客 本章介绍如何使用GLSurfaceView和GLSurfaceView.Renderer完成在Activity中的最简单实现. 1.在AndroidMan ...

  2. Netty之多用户的聊天室(三)

    Netty之多用户的聊天室(三) 一.简单说明 笔者有意将Netty做成一个系列的文章,因为笔者并不是一个善于写文章的人,而且笔者学习很多技术一贯的习惯就是敲代码,很多东西敲着敲着就就熟了,然后再进行 ...

  3. [js高手之路] vue系列教程 - 绑定设置属性的多种方式(5)

    一.设置属性的值: {{data中的数据}} window.onload = function () { var c = new Vue({ el : '#box', data : { url : ' ...

  4. HTML + CSS短标题(二,三,四文字长度)两端对齐的方式

    今天切图碰到了一个看似好弄,却并不好弄的文本两端对齐问题.如图1-1

  5. SQLAlchemy基础操作二

    多线程示例 import time import threading from sqlalchemy.ext.declarative import declarative_base from sqla ...

  6. Mongodb百亿级数据添加,修改,删除,查询等性能测试【四】

    集群的结构,大家可以查看我的另一遍文章,Mongodb的三种集群  在最后一种集群中,介绍到. 目前使用的数据就是最后一个测试集群,留下的数据. 简单介绍一下,四个分片的配置 192.168.99.6 ...

  7. COM学习(二)——COM的注册和卸载

    COM组件是跨语言的,组件被注册到注册表中,在加载时由加载函数在注册表中查找到对应模块的路径并进行相关加载.它的存储规则如下: 1. 在注册表的HKEY_CLASSES_ROOT中以模块名的方式保存着 ...

  8. KandQ:那年,那树,那些知识点

    写在前面:  对于数据结构的学习,注定绕不开"树"这一起着重要作用的数据结构."树"在整个数据结构的学习过程中具有举足轻重的地位,而与"树" ...

  9. MySQL并发复制系列二:多线程复制 2016

    并发复制(Parallel Replication) 系列二: Enhanced Multi-threaded Slaves作者:沃趣科技MySQL数据库工程师  麻鹏飞 首先梳理下传统MySQL/M ...

  10. kylin客户端(python编写)不能按照预期的segment进行rebuild

    kylin_client_tool 提供了对cube进行BUILD,REBUILD,MERGE功能,其中REBUILD却不能达到预期的效果按照指定的segment执行. 场景: 当我在kylin we ...