首页 > IT职业 > IT生活 > Mybatis源码分析-整体设计(一)
SSM是目前常见的构建Web项目的方案,Mybatis是其中重要的一环,如果能深刻的理解Mybatis的内部原理,对我们会有极大的帮助,接下来一起看看Mybatis的内部设计。
搭建Mybatis的基本运行环境,参考Mybatis入门
public static void main(String[] args) {
SqlSession sqlSession = null;
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 查询数据库内容
sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("me.aihe.dao.UserMapper.selectUser",1);
System.out.println(user);
// 插入数据库内容
} catch (IOException e) {
e.printStackTrace();
}finally {
if (sqlSession != null) {
sqlSession.close();
}
}
} Resources.getResourceAsStream("mybatis.xml");
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
} 

@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
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();
}
} sqlSession.selectOne("me.aihe.dao.UserMapper.selectUser",1); selectOne内部调用的是selectList的函数,selectList函数内部,首先获取到key对应的MappedStatement,然后通过Executor查询MapperStatement。
在解析配置的时候建立key与MappedStatement映射关系的
@Override
public List selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
} @Override
public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameter);
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
@SuppressWarnings("unchecked")
@Override
public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List list;
try {
queryStack++;
list = resultHandler == null ? (List) localCache.getObject(key) : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}
@Override
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);
}
} 
User user = sqlSession.selectOne("me.aihe.dao.UserMapper.selectUser",1);
这次大致看了下Mybatis的基本执行流程,涉及到了几个关键的类
创建SqlSessionFactory -> 获取SqlSession -> 获取->MappedStatement -> 获取StatementHandler同时创建Statement -> 执行Statement -> 使用ResultSet处理执行的结果,处理结果根据Mapperr.xml文件中指定的类型映射最终实现ORM功能
Mybatis的过程相比Spring MVC更直观一些,不过需要熟悉JDBC的知识,内部还有一些细节,后续继续研究
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2508/viewspace-2812745/ ,如需转载,请注明出处,否则将追究法律责任。