转载

mybatis 源码分析之 Configuration

mybatis 是 java 语言的 orm 框架, 使用教程 。

这篇主要介绍的是 mybatis 的 Configuration,教程 点击这里 。

XML 映射配置文件

configuration 节点下的属性:

  • configuration 配置
    • properties 属性
    • settings 设置
    • typeAliases 类型命名
    • typeHandlers 类型处理器
    • objectFactory 对象工厂
    • plugins 插件
    • environments 环境
      • environment 环境变量
        • transactionManager 事务管理器
        • dataSource 数据源
    • databaseIdProvider 数据库厂商标识
    • mappers 映射器

mybatis 的实现当中的 Configuration 基本上就是与这些属性相对应。

  protected Environment environment;    protected boolean safeRowBoundsEnabled = false;//settings 设置   ...省略一些属性   protected boolean callSettersOnNulls = false;    protected Properties variables = new Properties();//properties 属性   protected ObjectFactory objectFactory = new DefaultObjectFactory();//objectFactory 对象工厂   protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();   protected MapperRegistry mapperRegistry = new MapperRegistry(this);//mappers 映射器    protected final InterceptorChain interceptorChain = new InterceptorChain();//plugins 插件   protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();//typeHandler   protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();//typeAliases    protected String databaseId;  

mybatis 的执行流程

详细的执行流程 点击这里 。下面是简化的执行步骤:

  1. 构建 SqlSessionFactory
  2. 从 SqlSessionFactory 中获取 SqlSession
  3. 执行 sql
//step1 String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);  //step2 和 step3 SqlSession session = sqlSessionFactory.openSession(); try {   BlogMapper mapper = session.getMapper(BlogMapper.class);   Blog blog = mapper.selectBlog(101); } finally {   session.close(); } 

先从 SqlSessionFactoryBuilder 的源码入手:

public SqlSessionFactory build(Reader reader, String environment, Properties properties) {     try {       XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);       return build(parser.parse());     } catch (Exception e) {       throw ExceptionFactory.wrapException("Error building SqlSession.", e);     } finally {       ErrorContext.instance().reset();       try {         reader.close();       } catch (IOException e) {         // Intentionally ignore. Prefer previous error.       }     } }  public SqlSessionFactory build(Configuration config) {     return new DefaultSqlSessionFactory(config);   } 

代码也比较简单就是创建一个 XML 的解析器来解析传入的 XML,把 XML 转换成一个 Configuration 对象实例。

下面是 XMLConfigBuilder 当中的 parse 方法的代码:

 public Configuration parse() {     if (parsed) {       throw new BuilderException("Each XMLConfigBuilder can only be used once.");     }     parsed = true;     parseConfiguration(parser.evalNode("/configuration"));     return configuration;   }    private void parseConfiguration(XNode root) {     try {       //issue #117 read properties first       propertiesElement(root.evalNode("properties"));       typeAliasesElement(root.evalNode("typeAliases"));       pluginElement(root.evalNode("plugins"));       objectFactoryElement(root.evalNode("objectFactory"));       objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));       reflectionFactoryElement(root.evalNode("reflectionFactory"));       settingsElement(root.evalNode("settings"));       // read it after objectFactory and objectWrapperFactory issue #631       environmentsElement(root.evalNode("environments"));       databaseIdProviderElement(root.evalNode("databaseIdProvider"));       typeHandlerElement(root.evalNode("typeHandlers"));       mapperElement(root.evalNode("mappers"));     } catch (Exception e) {       throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);     }   } 

上面的代码清晰明了,就是解析 xml 当中的各个节点,然后设置到 configuration 对象的属性当中。

SqlSessionFactoryBuilder 最后 build 返回的是 DefaultSqlSessionFactory 实例,DefaultSqlSessionFactory 实现了 SqlSessionFactory 接口。下面看一下 openSession 的代码:

@Override   public SqlSession openSession() {     return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);   }   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {     Transaction tx = null;     try {       final Environment environment = configuration.getEnvironment();       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);       tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);       final Executor executor = configuration.newExecutor(tx, execType);       return new DefaultSqlSession(configuration, executor, autoCommit);     } catch (Exception e) {       closeTransaction(tx); // may have fetched a connection so lets call close()       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);     } finally {       ErrorContext.instance().reset();     }   } 

执行流程如下:

  1. 获取 environment
  2. 获取事务
  3. 创建 Executor
  4. 创建 DefaultSqlSession

后面详细分析这些类的作用。

最后看一下 DefaultSqlSession 类的查询执行流程:

@Override   public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {     try {       MappedStatement ms = configuration.getMappedStatement(statement);       return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);     } catch (Exception e) {       throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);     } finally {       ErrorContext.instance().reset();     }   } 

执行流程如下:

  1. 通过 statement 在 configuration 当中获取 sql 对应的 MappedStatement
  2. 然后 Executor 执行查询

---EOF---

原文  http://renchx.com/mybatis1
正文到此结束
Loading...