一、SqlSessionFactoryBuilder初始化sqlSessionFactory
static {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
try {
sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("baseDAO_resources/mybatis-config.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
我们调用了
Resources.getResourceAsReader("baseDAO_resources/mybatis-config.xml")
去加载我们预定义好的配置文件,用使用到的classLoader去加载文件,取到类加载器需要的URL,使用URL开启流,并开启流返回。在使用Resource的静态方法,将流封装成Reader返回。
然后调用了
sqlSessionFactoryBuilder.build(
Resources.getResourceAsReader("baseDAO_resources/mybatis-config.xml")
);
使用sqlSessionFactoryBuilder中的build方法,根据Reader去读取xml中的内容。
我们看到SqlSessionFactory的源码如下:
public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
}
public SqlSessionFactory build(Reader reader, String environment) {
return build(reader, environment, null);
}
public SqlSessionFactory build(Reader reader, Properties properties) {
return build(reader, null, properties);
}
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.
}
}
}
有多个build方法,其实都是调用了同一个build:
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.
}
}
}
这个build又调用了
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
事实上,Mybatis使用了
XMLConfigBuilder
这个类去解析Reader,也就是我们自己去配置的xml文件,将xml文件解析成Configuration对象,
解析成Configuration对象的具体过程我们将在后面阐述。先大体建立如何创建sqlSession的过程,再去描述具体细节、
这里使用了工厂模式 可以点击这里了解工厂模式的相关内容,这里的SqlSessionFactory就是抽象工厂,SqlSession就是对应的产品接口,DefaultSqlSessionFactory就是我们自己实现的工厂,DefaultSqlSession就是具体的产品。
当用户拿到了DefaultSqlSessionFactory后就可以使用openSession去创建一个对应工厂的产品了
我们可以看一下DefaultSqlSessionFactory的源码
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
这里调用了openSessionFromDataSource方法,来创建一个我们想要的SqlSession以供用户去使用
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();
}
}
追下去
DefaultSqlSession:
public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
private Executor executor;
private boolean autoCommit;
private boolean dirty;
private List<Cursor<?>> cursorList;
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
}
可以看到,Mybatis根据我们自己在Xml中的配置,封装了一个sqlSession以供用户使用。其中,关于
Configuration 、Executor 、是否自动提交等信息,已经初始化到sqlSession中,我们就可以拿到sqlSession愉快的CRUD了!!
在第四部分我们将讲述,sqlSession的作用和原理。