mybatis_helloworld(2)_源码
来源:互联网 发布:录制视频软件 知乎 编辑:程序博客网 时间:2024/06/13 02:51
在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();//打开sessionnew Test1().insert(session);}
1. XML文件资源的获取
a)包路径:org.apache.ibatis.io
b)Resources类:定义了一系列的静态方法,用于获取资源(ClassLoader,URL,InputStream,Read,File,Properties,Charset)
c)我们用到的getResourceAsReader,getResourceAsStream方法
public static Reader getResourceAsReader(String resource) throws IOException { Reader reader;
· //利用InputStream构造Reader if(charset == null) reader = new InputStreamReader(getResourceAsStream(resource)); else reader = new InputStreamReader(getResourceAsStream(resource), charset); return reader; }
public static InputStream getResourceAsStream(String resource) throws IOException {
//调用重载方法 return getResourceAsStream(null, resource); }
public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
//调用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; }
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)_源码
- MyBatis_HelloWorld
- Mybatis_HelloWorld 快速入门
- [VB.NET源码]2_消息提示
- Struts2 源码阅读(2)_扩展阅读
- Struts2 源码阅读(2)_扩展阅读
- Android_4.2_源码下载和编译环境安装及Android_4.2_源码编译
- 03_源码编译
- 百鸡百钱问题_源码
- [VB.NET源码]47_使用画笔(2)
- ibatis源码学习2_初始化和配置文件解析
- 源码_秒赞网站源码
- Okhttp3的源码分析_小白看源码
- Eclipse快捷键_源码研究
- wordpress主题结构_源码
- LibreOffice源码开发 _排版
- AsyncTask源码分析_顾梁
- Spring MVC学习指南_源码
- 大数据:技术与应用实践指南(中国工程院院士倪光南倾情作序,雷万云、毛新生、段永朝、安晖联合力荐)
- 怎样编写Apple Push Notification服务器
- initrd网络转载
- 结构和类的区别
- 使用XmlReader读取xml文件
- mybatis_helloworld(2)_源码
- Linux Crontab 定时任务 命令详解
- "+y does not work
- 目前读书大概情况
- cenos jdk install and enviorment
- druid连接池的简单例子
- Gauss-Jordan消去法中完全选主元法求解线性方程组
- C语言 变量和函数命名规范
- Sereja ans Anagrams ------Codeforces Round # 215 div.1 B