public static void main(String[] args) throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
//通过sqlSessionFactory获取SqlSession
SqlSession session = sqlSessionFactory.openSession() {
//方式一:
UserMapper mapper = session.getMapper(UserMapper.class);
User user1 = mapper.selectBlog("1");
//方式二:
User user2 = session.selectOne(
"test.UserMapper.selectBlog", 1);
}
通过MyBatis源码解析(二):构建sqlSessionFactory,得到了sqlSessionFactory。通过 SqlSessionFactory 去获取 SqlSession 对象。
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//之前解析配置文件中Environment节点数据,并放入了configuration
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//获取Executor,通过execType获取指定类型的Executor。可选有三种执行器
/**
* public enum ExecutorType {
* SIMPLE, REUSE, BATCH
* }
*
*/
final Executor executor = configuration.newExecutor(tx, execType);
//通过configuration 和 执行器executor 构建DefaultSqlSession
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();
}
}
/**
* 通过executorType参数获取指定类型的执行器
* @param transaction
* @param executorType
* @return
*/
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
//默认执行器类型:defaultExecutorType = ExecutorType.SIMPLE;
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
SimpleExecutor:
每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象:closeStatement(stmt);
/**
* SimpleExecutor 每次获取新的Statement
* @param handler
* @param statementLog
* @return
* @throws SQLException
*/
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return stmt;
}
ReuseExecutor:
重复使用Statement对象。当执行update或select,以sql作为key从statementMap查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。
/**
* BatchExecutor获取重用Statement
* @param handler
* @param statementLog
* @return
* @throws SQLException
*/
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
BoundSql boundSql = handler.getBoundSql();
String sql = boundSql.getSql();
//判断statementMap是否包含key为sql的Statement对象
if (hasStatementFor(sql)) {
stmt = getStatement(sql);
applyTransactionTimeout(stmt);
} else {
//如果不包含新开启一个Statement,并放入statementMap
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
putStatement(sql, stmt);
}
handler.parameterize(stmt);
return stmt;
}
/**
* 判断statementMap是否包含key为sql的Statement对象
* @param sql
* @return
*/
private boolean hasStatementFor(String sql) {
try {
return statementMap.keySet().contains(sql) && !statementMap.get(sql).getConnection().isClosed();
} catch (SQLException e) {
return false;
}
}
BatchExecutor:
执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
构建SqlSession:
最后通过configuration 和 执行器executor 构建DefaultSqlSession
return new DefaultSqlSession(configuration, executor, autoCommit);