mybatis 是 java 语言的 orm 框架, 使用教程 。
这篇主要介绍的是 mybatis 的 Configuration,教程 点击这里 。
XML 映射配置文件
configuration 节点下的属性:
- configuration 配置
- properties 属性
- settings 设置
- typeAliases 类型命名
- typeHandlers 类型处理器
- objectFactory 对象工厂
- plugins 插件
- environments 环境
- environment 环境变量
- transactionManager 事务管理器
- dataSource 数据源
- environment 环境变量
- 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 的执行流程
详细的执行流程 点击这里 。下面是简化的执行步骤:
- 构建 SqlSessionFactory
- 从 SqlSessionFactory 中获取 SqlSession
- 执行 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(); } }
执行流程如下:
- 获取 environment
- 获取事务
- 创建 Executor
- 创建 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(); } }
执行流程如下:
- 通过 statement 在 configuration 当中获取 sql 对应的 MappedStatement
- 然后 Executor 执行查询
---EOF---