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

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

XML 映射配置文件

configuration 节点下的属性:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
1
2
3
4
5
6
7
8
9
10
11
12
13
//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 的源码入手:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 方法的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@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 类的查询执行流程:

1
2
3
4
5
6
7
8
9
10
11
@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—