上一篇文章我们初始化了mybatis的环境。这一次我们看看打开会话和数据库的操作。
在上面的顺序图中,我们可以看到DefaultSqlSessionFactory主要的交互对象还是Configuration,网络上有人喜欢叫他是mybatis的大总管,是的它管理和配置很多东西,在这里我们获取了ExecutorType,getEnvironment和Transaction。并且让它帮忙我们生成了重要的Executor。我们先看看这个Executor类的继承情况。
部分源代码:
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
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;
}
在openSession顺序图中创建了这个DefaultSqlSession类,并且把configuration, executor, autoCommit这三个参数都传给了DefaultSqlSession对象。它主要完成SqlSession接口定义的内容。
SqlSession主要接口定义
T selectOne(String statement);
T selectOne(String statement, Object parameter);
<E> List<E> selectList(String statement);
<E> List<E> selectList(String statement, Object arameter);
<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
<K, V> Map<K, V> selectMap(String statement, String mapKey);
<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
void select(String statement, Object parameter, ResultHandler handler);
void select(String statement, ResultHandler handler);
void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
int insert(String statement);
int insert(String statement, Object parameter);
int update(String statement);
int update(String statement, Object parameter);
int delete(String statement);
int delete(String statement, Object parameter);
void commit();
void commit(boolean force);
void rollback();
void rollback(boolean force);
DefaultSqlSession所要做的事情就是根据参数(例如执行语句的String)获取MappedStatement 对象(MyBatis代码分析之(一)创建)。再把客户端传递过来的参数(例如一个对象User)传递给具体的Executor(openSession创建)去执行查询,新增、修改、删除和事务动作。
//DefaultSqlSession中
public List selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
List result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
return result;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public int update(String statement, Object parameter) {
try {
dirty = true;
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public int insert(String statement, Object parameter) {
return update(statement, parameter);//调用updage
}
public int delete(String statement, Object parameter) {
return update(statement, parameter);//调用updage
}
public void commit(boolean force) {
try {
executor.commit(isCommitOrRollbackRequired(force));
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public void rollback(boolean force) {
try {
executor.rollback(isCommitOrRollbackRequired(force));
dirty = false;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error rolling back transaction. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
下面我们分析的是执行一个查询的过程。执行环境都是系统默认的情况。
- 顺序图
在这个顺序图中我们可以看到mybatis先调用了CachingExecutor(这里忽略了部分代码和对象),去缓存中去查询,若缓存没有再调用包装进去的Executor对象(这里是SimpleExecutor)。然后mybatis把创建StatementHandler又一次交给了Configuration类。它根据MappedStatement的执行类型创建不同的处理类。
这里的StatementHandler和上面的CachingExecutor有点类似。也是弄了一个代理。先调用RoutingStatementHandler,再调用代理的对象。
然后就简单了 ,准备连接数据库,参数化对象,执行查询。
public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.update(stmt);
} finally {
closeStatement(stmt);
}
}
有兴趣的可以去看看更新的顺序图,道理是一样的,最后调用的是 return handler.update(stmt);。