从上一篇中,我们找到了我们的切入点SqlSessionFactory,那么现在我们就来会会它.
(注:本文中出现的代码全是出自mybatis-3.2.6版本的源码)
SqlSessionFactory在mybatis被定义为一个接口,在实际使用时,我们一般会通过SqlSessionFactoryBuilder的 build方法来构造一个SqlSessionFactory:
// Reader是配置文件的输入流
public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
// parser.parse()方法将xml文件中的配置信息转化为Configuration对象
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方法,但是最终都会调用该方法,传入一个Configuration
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
从上述代码我们得知,SqlSessionFactory默认的实现为DefaultSqlSessionFactory,而DefaultSqlSessionFactory中最主要的也是唯一一个成员变量也就是Configuration.
我们也知道SqlSessionFactory的作用就是用来生成一个SqlSession,因为从上篇文章中的例子来看,我们最终是通过调用SqlSession的方法去和数据库进行交互,那么我们现在来看看DefaultSqlSessionFactory生成SqlSession的代码:
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
public SqlSession openSession(boolean autoCommit) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
}
public SqlSession openSession(Connection connection) {
return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
}
public SqlSession openSession(ExecutorType execType, Connection connection) {
return openSessionFromConnection(execType, connection);
}
......
DefaultSqlSessionFactory中还有很多openSession的重载方法,但是实际上最终都是去调用openSessionFromDataSource方法和openSessionFromConnection方法,我们继续看这两个方法的代码:
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);
// 最终返回的SqlSession是DefaultSqlSession
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
try {
boolean autoCommit;
try {
autoCommit = connection.getAutoCommit();
} catch (SQLException e) {
autoCommit = true;
}
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
final Transaction tx = transactionFactory.newTransaction(connection);
final Executor executor = configuration.newExecutor(tx, execType);
// 最终返回的SqlSession是DefaultSqlSession
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
从上述代码我们可以看出,实际上我们最终要使用的SqlSession是DefaultSqlSession,并且DefaultSqlSession传入了Configuration(xml文件转换的Configuration信息),Executor(最终由该类去执行sql语句)和autoCommit(是否自动提交).
看到这里,相信大家和我一样都有点混乱了,刚找好的SqlSessionFactory切入点又散开了,出现了Configuration,Executor.
而在生成Executor时,又出现了Transaction,TransactionFactory等一系列相关类.不过不要紧,我们可以发现,核心都是围绕着Configuration类的,所以我们先看Configuration,所以,我们就要看看刚开始的parser.parse()方法是把xml配置文件转化为怎么样的一个Configuration类.
本文深入探讨了MyBatis中SqlSessionFactory的创建过程,包括如何通过SqlSessionFactoryBuilder构造SqlSessionFactory,以及其内部如何利用Configuration配置信息生成SqlSession。
513

被折叠的 条评论
为什么被折叠?



