• mybatis_helloworld(2)_源码


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

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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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方法

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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方法

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

    2. 构建SqlSessionFactory,初始化资源

    a) SqlSessionFactory接口介绍

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public interface SqlSessionFactory  
    2. {  
    3.     //定义了一系列获取Session的方法,获取Configuration的方法  
    4.     public abstract SqlSession openSession();  
    5.   
    6.     public abstract SqlSession openSession(boolean flag);  
    7.   
    8.     public abstract SqlSession openSession(Connection connection);  
    9.   
    10.     public abstract SqlSession openSession(TransactionIsolationLevel transactionisolationlevel);  
    11.   
    12.     public abstract SqlSession openSession(ExecutorType executortype);  
    13.   
    14.     public abstract SqlSession openSession(ExecutorType executortype, boolean flag);  
    15.   
    16.     public abstract SqlSession openSession(ExecutorType executortype, TransactionIsolationLevel transactionisolationlevel);  
    17.   
    18.     public abstract SqlSession openSession(ExecutorType executortype, Connection connection);  
    19.   
    20.     public abstract Configuration getConfiguration();  
    21. }  

    b) SqlSessionFactory接口构建

       i. SqlSessionFactoryBuilder类:构建SqlSessionFactory

       ii. 我们使用的方法:build

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

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

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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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.   
    14.    private void parseConfiguration(XNode root)  
    15.    {  
    16.        try  
    17.        {  
    18.            typeAliasesElement(root.evalNode("typeAliases"));    //解析typeAliases  
    19.            pluginElement(root.evalNode("plugins"));  
    20.            objectFactoryElement(root.evalNode("objectFactory"));  
    21.            objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));  
    22.            propertiesElement(root.evalNode("properties"));  
    23.            settingsElement(root.evalNode("settings"));  
    24.            environmentsElement(root.evalNode("environments"));   //数据库配置  
    25.            typeHandlerElement(root.evalNode("typeHandlers"));      
    26.            mapperElement(root.evalNode("mappers"));    //解析sql语句配置文件  
    27.        }  
    28.        catch(Exception e)  
    29.        {  
    30.            throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);  
    31.        }  
    32.    }  

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

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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();这行代码的实现

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

    4. insert数据的实现

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

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

       i. 调用哪个executor?

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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方法实现

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    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.       
    16.     //子类SimpleExecutor重写了doUpdate方法  
    17.     public int doUpdate(MappedStatement ms, Object parameter)  
    18.         throws SQLException  
    19.     {  
    20.         //java.sql.Statement  
    21.         Statement stmt = null;  
    22.         int i;  
    23.         try  
    24.         {  
    25.             Configuration configuration = ms.getConfiguration();  
    26.             StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null);  
    27.             //大概就是拼Sql,生成对应的Statement,执行Sql,封装数据了(这块比较复杂,下次再看了)  
    28.             stmt = prepareStatement(handler);  
    29.               
    30.             i = handler.update(stmt);  
    31.         }  
    32.         finally  
    33.         {  
    34.             closeStatement(stmt);  
    35.         }  
    36.         return i;  
    37.     }  

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

  • 相关阅读:
    MyEclipse的配置--博客园老牛大讲堂
    Hbuilder连接夜神模拟器---博客园老牛大讲堂
    APICloud连接夜神模拟器--博客园老牛大讲堂
    H5混合开发APP配置以及第一个工程--博客园老牛大讲堂
    实现标签页(菜单栏)--博客园老牛大讲堂
    H5动态添加数据-博客园老牛大讲堂
    bootstrap实现网页手风琴--博客园老牛大讲堂
    返回零长度的数组或集合,而不是null
    用EnumMap代替序数索引
    用EnumSet代替位域
  • 原文地址:https://www.cnblogs.com/haimishasha/p/5710627.html
Copyright © 2020-2023  润新知