Before executing SQL operations, MyBatis requires initialization: loading configuration resources, parsing them into an internal representation, and finally producing a SqlSession instance. This process involves three key stages:
- Obtaining a configuration
InputStreamviaResources.getResourceAsStream() - Building a
SqlSessionFactoryusingSqlSessionFactoryBuilder.build() - Creating a
SqlSessionviaSqlSessionFactory.openSession()
The typical bootstrap sequence looks like this:
InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
SqlSession session = factory.openSession();
- How
Resources.getResourceAsStream()Resolves Configuration Files
This utility method abstracts classloader-aware resource resolution. It attempts to locate the specified file across multiple classloader contexts in a prioritized order.
Internally, it delegates to a ClassLoaderWrapper, which aggregates several candidate loaders:
- The explicitly passed
ClassLoader(if non-null) - The default loader configured in
Resources - The current thread’s context classloader
- The classloader that loaded the
Resourcesclass itself - The system classloader
The wrapper iterates through this list, invoking getResourceAsStream(resource) on each until one returns a non-null stream. If the initial lookup fails and the path lacks a leading slash, it retries with "/" + resource.
Under the hood, each ClassLoader resolves the resource by converting it to a URL (via getResource()) and opening its stream (url.openStream()). The URL resolution follows the delegation model—first consulting parent loaders, then falling back to the bootstrap classpath (e.g., sun.misc.Launcher.getBootstrapClassPath()) and finally custom findResource() implementations.
- Parsing Configuration and Building
SqlSessionFactory
The SqlSessionFactoryBuilder.build(InputStream) method orchestrates XML parsing and factory construction:
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String env, Properties props) {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, env, props);
Configuration config = parser.parse();
return build(config);
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
The XMLConfigBuilder parses the input stream into a Configuration object—populating settings, mappers, type aliases, plugins, and environment details. Once parsed, the builder wraps it in a DefaultSqlSessionFactory, which serves as the factory for session instances.
- Instantiating
SqlSessionfromSqlSessionFactory
DefaultSqlSessionFactory.openSession() is a convenience method that delegates to openSessionFromDataSource(), specifying default execution behavior:
public SqlSession openSession() {
return openSessionFromDataSource(
configuration.getDefaultExecutorType(),
null,
false
);
}
The core logic inside openSessionFromDataSource() includes:
- Retrieving the
EnvironmentfromConfiguration - Instantiating a
TransactionFactorybased on the environment’s transaction manager type - Creating a
Transactionbound to the data source, isolation level, and auto-commit settting - Constructing an
Executor(e.g.,SimpleExecutor,CachingExecutor) wrapped around the transaction - Returning a new
DefaultSqlSessioninitialized with the configuration, executor, and auto-commit flag
This final step yields a fully functional SqlSession ready for CRUD operations, statement execution, and transaction control.