mybatis_helloworld(2)_源码
摘录自:http://blog.csdn.net/y172158950/article/details/16982123
在helloworld(1)中,分析了insert一条数据的流程,现在分析下源码:
- public static void main(String args[]) throws IOException {
- String resource = "com/test/configuration.xml";//获得xml(Mybatis)数据库连接的连接
- Reader reader = Resources.getResourceAsReader(resource);//读取里面的文件
- SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
- .build(reader);//创建session工厂
- SqlSession session = sessionFactory.openSession();//打开session
- new Test1().insert(session);
- }
1. XML文件资源的获取
a)包路径:org.apache.ibatis.io
b)Resources类:定义了一系列的静态方法,用于获取资源(ClassLoader,URL,InputStream,Read,File,Properties,Charset)
c)我们用到的getResourceAsReader,getResourceAsStream方法
- <p> public static Reader getResourceAsReader(String resource)
- throws IOException
- {
- Reader reader;</p><p>· //利用InputStream构造Reader
- if(charset == null)
- reader = new InputStreamReader(getResourceAsStream(resource));
- else
- reader = new InputStreamReader(getResourceAsStream(resource), charset);
- return reader;
- }</p><p> </p><p> public static InputStream getResourceAsStream(String resource)
- throws IOException
- {</p><p> //调用重载方法
- return getResourceAsStream(null, resource);
- }</p><p> </p><p> public static InputStream getResourceAsStream(ClassLoader loader, String resource)
- throws IOException
- {</p><p> //调用ClassLoaderWrapper类的方法,利用ClassLoader获取资源
- InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
- if(in == null)
- throw new IOException((new StringBuilder()).append("Could not find resource ").append(resource).toString());
- else
- return in;
- }</p>
d)ClassLoaderWrapper类:封装了一个ClassLoader数组,通过ClassLoader获取资源
e)我们用到的getResourceAsStream,getClassLoaders方法
- public InputStream getResourceAsStream(String resource, ClassLoader classLoader)
- {
- return getResourceAsStream(resource, getClassLoaders(classLoader));
- }
- ClassLoader[] getClassLoaders(ClassLoader classLoader)
- {
- return (new ClassLoader[] { //构建新的ClassLoader列表,包含用户创建及默认
- classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), systemClassLoader});
- }
- InputStream getResourceAsStream(String resource, ClassLoader classLoader[])
- {
- ClassLoader arr$[] = classLoader;
- int len$ = arr$.length;
- for(int i$ = 0; i$ < len$; i$++) //遍历ClassLoader数组,当某一个Loader成功构建资源则返回
- {
- ClassLoader cl = arr$[i$];
- if(null == cl)
- continue;
- InputStream returnValue = cl.getResourceAsStream(resource);
- if(null == returnValue)
- returnValue = cl.getResourceAsStream((new StringBuilder()).append("/").append(resource).toString());
- if(null != returnValue)
- return returnValue;
- }
- return null;
- }
2. 构建SqlSessionFactory,初始化资源
a) SqlSessionFactory接口介绍
- public interface SqlSessionFactory
- {
- //定义了一系列获取Session的方法,获取Configuration的方法
- public abstract SqlSession openSession();
- public abstract SqlSession openSession(boolean flag);
- public abstract SqlSession openSession(Connection connection);
- public abstract SqlSession openSession(TransactionIsolationLevel transactionisolationlevel);
- public abstract SqlSession openSession(ExecutorType executortype);
- public abstract SqlSession openSession(ExecutorType executortype, boolean flag);
- public abstract SqlSession openSession(ExecutorType executortype, TransactionIsolationLevel transactionisolationlevel);
- public abstract SqlSession openSession(ExecutorType executortype, Connection connection);
- public abstract Configuration getConfiguration();
- }
b) SqlSessionFactory接口构建
i. SqlSessionFactoryBuilder类:构建SqlSessionFactory
ii. 我们使用的方法:build
- public SqlSessionFactory build(Reader reader)
- {
- //调用重载方法
- return build(reader, null, null);
- }
- public SqlSessionFactory build(Reader reader, String environment, Properties properties)
- {
- try
- {
- SqlSessionFactory sqlsessionfactory;
- try
- {
- //根据reader封装XMLConfig相关信息
- XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
- //调用重载方法
- sqlsessionfactory = build(parser.parse());
- }
- catch(Exception e)
- {
- throw ExceptionFactory.wrapException("Error building SqlSession.", e);
- }
- return sqlsessionfactory;
- }
- finally
- {
- ErrorContext.instance().reset();
- try
- {
- reader.close();
- }
- catch(IOException e) { }
- }
- }
- public SqlSessionFactory build(Configuration config)
- {
- //依据配置信息构建默认的SqlSessionFactory实现
- return new DefaultSqlSessionFactory(config);
- }
c) XMLConfigBuilder类:解析XML配置文件
i. 用到的主要方法:parse,parseConfiguration(就是按XML结构顺序解析,分别获取配置[SAX解析]);将数据封装到父类的configuration对象中
- public Configuration parse()
- {
- if(parsed)
- {
- throw new BuilderException("Each MapperConfigParser can only be used once.");
- } else
- {
- parsed = true;
- parseConfiguration(parser.evalNode("/configuration")); //XML文件的根目录
- return configuration;
- }
- }
- private void parseConfiguration(XNode root)
- {
- try
- {
- typeAliasesElement(root.evalNode("typeAliases")); //解析typeAliases
- pluginElement(root.evalNode("plugins"));
- objectFactoryElement(root.evalNode("objectFactory"));
- objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
- propertiesElement(root.evalNode("properties"));
- settingsElement(root.evalNode("settings"));
- environmentsElement(root.evalNode("environments")); //数据库配置
- typeHandlerElement(root.evalNode("typeHandlers"));
- mapperElement(root.evalNode("mappers")); //解析sql语句配置文件
- }
- catch(Exception e)
- {
- throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);
- }
- }
d)Configuration类:基本就是封装一系列的数据;看一下成员变量
- protected Environment environment;
- protected boolean lazyLoadingEnabled;
- protected boolean aggressiveLazyLoading;
- protected boolean multipleResultSetsEnabled;
- protected boolean useGeneratedKeys;
- protected boolean useColumnLabel;
- protected boolean cacheEnabled;
- protected Integer defaultStatementTimeout;
- protected ExecutorType defaultExecutorType;
- protected AutoMappingBehavior autoMappingBehavior;
- protected Properties variables;
- protected ObjectFactory objectFactory;
- protected ObjectWrapperFactory objectWrapperFactory;
- protected MapperRegistry mapperRegistry;
- protected final InterceptorChain interceptorChain;
- protected final TypeHandlerRegistry typeHandlerRegistry;
- protected final TypeAliasRegistry typeAliasRegistry;
- protected final Map mappedStatements;
- protected final Map caches;
- protected final Map resultMaps;
- protected final Map parameterMaps;
- protected final Map keyGenerators;
- protected final Set loadedResources;
- protected final Map sqlFragments;
- protected final Collection incompleteStatements;
- protected final Collection incompleteCacheRefs;
- protected final Map cacheRefMap;
e)DefaultSqlSessionFactory类:SqlSessionFactory接口实现类,并持有一个Configuration对象;我们实现获取SqlSeesion对象应用的此类的方法。
3. 回过头来,再看看SqlSession session = sessionFactory.openSession();这行代码的实现
- public SqlSession openSession()
- {
- return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
- }
- private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
- {
- Connection connection = null;
- try
- {
- DefaultSqlSession defaultsqlsession;
- try
- {
- Environment environment = configuration.getEnvironment();
- //获取javax.sql.DataSource
- DataSource dataSource = getDataSourceFromEnvironment(environment);
- TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
- //获取java.sql.Connection
- connection = dataSource.getConnection();
- if(level != null)
- connection.setTransactionIsolation(level.getLevel());
- connection = wrapConnection(connection);
- //一系列的封装,把Connection包装成了DefaultSqlSession(SqlSession的实现类)
- org.apache.ibatis.transaction.Transaction tx = transactionFactory.newTransaction(connection, autoCommit);
- org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
- defaultsqlsession = new DefaultSqlSession(configuration, executor, autoCommit);
- }
- catch(Exception e)
- {
- closeConnection(connection);
- throw ExceptionFactory.wrapException((new StringBuilder()).append("Error opening session. Cause: ").append(e).toString(), e);
- }
- return defaultsqlsession;
- }
- finally
- {
- ErrorContext.instance().reset();
- }
- }
4. insert数据的实现
- public int insert(String statement, Object parameter)
- {
- return update(statement, parameter);
- }
- public int update(String statement, Object parameter)
- {
- try
- {
- int i;
- try
- {
- dirty = true;
- //根据Mapper.xml配置文件中的id找到Sql语句
- org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
- //这个执行器是不是见过?构建DefaultSqlSession时传过来的
- // org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
- i = executor.update(ms, wrapCollection(parameter));
- }
- catch(Exception e)
- {
- throw ExceptionFactory.wrapException((new StringBuilder()).append("Error updating database. Cause: ").append(e).toString(), e);
- }
- return i;
- }
- finally
- {
- ErrorContext.instance().reset();
- }
- }
a) 找一下executor,看看其update方法
i. 调用哪个executor?
- public Executor newExecutor(Transaction transaction, ExecutorType executorType)
- {
- executorType = executorType != null ? executorType : defaultExecutorType; //我们使用的是默认的Type(SIMPLE)
- executorType = executorType != null ? executorType : ExecutorType.SIMPLE;
- 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;
- }
ii. SimpleExecutor的update方法实现
- //父类BaseExecutor的update方法,调用了doUpdate方法
- public int update(MappedStatement ms, Object parameter)
- throws SQLException
- {
- ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
- if(closed)
- {
- throw new ExecutorException("Executor was closed.");
- } else
- {
- clearLocalCache();
- return doUpdate(ms, parameter);
- }
- }
- //子类SimpleExecutor重写了doUpdate方法
- public int doUpdate(MappedStatement ms, Object parameter)
- throws SQLException
- {
- //java.sql.Statement
- Statement stmt = null;
- int i;
- try
- {
- Configuration configuration = ms.getConfiguration();
- StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null);
- //大概就是拼Sql,生成对应的Statement,执行Sql,封装数据了(这块比较复杂,下次再看了)
- stmt = prepareStatement(handler);
- i = handler.update(stmt);
- }
- finally
- {
- closeStatement(stmt);
- }
- return i;
- }
看了一回源码,也感觉高端大气上档次了,下次画个图
mybatis_helloworld(2)_源码的更多相关文章
- java画图程序_图片用字母画出来_源码发布_版本二
在上一个版本:java画图程序_图片用字母画出来_源码发布 基础上,增加了图片同比例缩放,使得大像素图片可以很好地显示画在Notepad++中. 项目结构: 运行效果1: 原图:http://imag ...
- pygame系列_小球完全弹性碰撞游戏_源码下载
之前做了一个基于python的tkinter的小球完全碰撞游戏: python开发_tkinter_小球完全弹性碰撞游戏_源码下载 今天利用业余时间,写了一个功能要强大一些的小球完全碰撞游戏: 游戏名 ...
- Django_Restframwork_APIVIEW视图_源码分析
Django _VIEW视图_源码分析
- java画图程序_图片用字母画出来_源码发布
在之前写了一篇blog:java画图程序_图片用字母画出来 主要是把一些调试的截图发布出来,现在程序调试我认为可以了(当然,你如果还想调试的话,也可以下载源码自己调试). 就把源码发布出来. 项目结构 ...
- 软件包管理_rpm命令管理_yum工具管理_文件归档压缩_源码包管理
rpm命令管理软件 对于挂载的像U盘那种都会在midea目录下,但是会显示在桌面上 安装软件(i:install,v:verbose冗长的,h:human):rpm -ivh xxxx.rpm 安 ...
- bootstrap_栅格系统_响应式工具_源码分析
-----------------------------------------------------------------------------margin 为负 使盒子重叠 等高 等高 ...
- QT_文本编辑器_源码下载
源码下载: 链接: http://pan.baidu.com/s/1c21EVRy 密码: qub8 实现主要的功能有:新建,打开,保存,另存为,查找(查找的时候需要先将光标放到最下面位置才能查全,不 ...
- 『TensorFlow Internals』笔记_源码结构
零.资料集合 知乎专栏:Bob学步 知乎提问:如何高效的学习 TensorFlow 代码?. 大佬刘光聪(Github,简书) 开源书:TensorFlow Internals,强烈推荐(本博客参考书 ...
- pygame系列_font游戏字体_源码下载
在pygame游戏开发中,一个友好的UI中,漂亮的字体是少不了的 今天就给大伙带来有关pygame中字体的一些介绍说明 首先我们得判断一下我们的pygame中有没有font这个模块 if not py ...
随机推荐
- Javascipt数组
Javascipt数组 在Javascript中数组的做用是:使用单独的变量名来储存一系列的值. 数组只有一个属性,就是length,length表示的数组所占内存空间的数目. <!DOCTYP ...
- ABP架构学习系列三:手工搭建ABP框架
由于公司的项目才接触到ABP这个框架,当时就觉得高大上,什么IOC.AOP.ddd各种专业词汇让人激情 澎湃,但在使用过程中碰到了许多坑,可能也许是没有去看源码导致的,但工作确实没有那么多时间让人去慢 ...
- sql server 各种等待类型-转
等待的类型 资源等待 当某个工作线程请求访问某个不可用的资源(因为该资源正在由其他某个工作线程使用,或者该资源尚不可用)时,便会发生资源等待.资源等待的示例包括锁等待.闩锁等待.网络等待以及磁盘 I/ ...
- 表单验证插件--formvalidation
表单验证是一个非常基础的功能,当你的表单项少的时候,可以自己写验证,但是当你的表单有很多的时候,就需要一些验证的插件.今天介绍一款很好用的表单验证插件,formvalidation.其前身叫做boot ...
- ASP.NET 设计模式:应用程序分层与关注点分离(SoC)
应用程序分层设计 应用程序分层属于关注点分离的一种形式,可以通过命名空间.文件夹或采用单独的项目来实现. 下图为一个采用分层设计的项目结构 ASPPatterns.Chap3.Layered.Repo ...
- MariaDB日志审计 帮你揪出内个干坏事儿的小子
Part1:谁干的? 做DBA的经常会遇到,一些表被误操作了,被truncate.被delete.甚至被drop.引起这方面的原因大多数都是因为人为+权限问题导致的.一些公共账户,例如ceshi账户, ...
- iOS 横竖屏适配 笔记
研究消息转发机制 已经一周多了,但是 还是没整理出博客, 还是先写一个 项目中遇到的 横竖屏适配问题. // 开启自动转屏 - (BOOL)shouldAutorotate { return YES; ...
- js,jq.事件代理(事件委托)复习。
<ul id = "lists"> <li>列表1</li> <li>列表2</li> <li>列表3< ...
- 论python3下“多态”与“继承”中坑
1.背景: 近日切换到python3后,发现python3在多态处理上,有一些比较有意思的情况,特别记载,供大家参考... 以廖老师的python3教程中的animal 和dog的继承一节的代码做例子 ...
- HttpClient 模拟发送Post和Get请求 并用fastjson对返回json字符串数据解析,和HttpClient一些参数方法的deprecated(弃用)的综合总结
最近在做一个接口调用的时候用到Apache的httpclient时候,发现引入最新版本4.5,DefaultHttpClient等老版本常用的类已经过时了,不推荐使用了:去官网看了一下在4.3之后就抛 ...