Mybatis查询源代码分析
mybatis
作为常用的 orm
框架,极大的简化了我们手写jdbc代码的情况,其中它的设计还是蛮有意思的
jdbc 执行查询
在不使用 mybatis
的情况下,使用刚入门的 jdbc
执行一次查询的过程如下
public class App {
public static void main(String[] args) throws Exception {
Connection connection = DriverManager.getConnection("xx", null);
PreparedStatement preparedStatement = connection.prepareStatement("select * from `user` where id = ?");
preparedStatement.setInt(1, 1);
preparedStatement.execute();
ResultSet resultSet = getFirstResult(preparedStatement);
if (resultSet != null) {
while (resultSet.next()) {
//获取 pojo 对象
User user = new User();
...//填充数据
}
}
}
private static ResultSet getFirstResult(Statement statement) throws SQLException {
ResultSet resultSet = statement.getResultSet();
while (resultSet == null) {
if (statement.getMoreResults()) {
resultSet = statement.getResultSet();
} else {
if (statement.getUpdateCount() == -1) {
// no more results. Must be no resultset
break;
}
}
}
return resultSet;
}
这个过程基本上可以概括为如下
- 获取物理链接(Connection) ——> 第三行
- 预编译 ——> 第四行,设置resultSet参数
- 设置参数 + 执行sql ——> 第五行+第六行
- 处理结果集 ——> 第7行到结束
整个 mybatis
的处理流程也是一致的,从根本上简化了我们写jdbc的代码,同时也带来了一定的损耗(相对于jdbc而言),但是这点损耗和维护性来说,是值得接受的
mybatis 执行查询
mybatis
执行一次查询的过程如下
- 读取配置文件,获取
SqlSessionFactoryBuilder
- 解析配置文件,获取
SqlSessionFactory
- 解析
configuration.xml
- 解析配置的属性元素,例如
cacheEnabled
localCacheScope
, 解析别名等等。 - 解析
mapper.xml
文件- 解析
ResultMap
,paratemerMap
sql
curd
节点,为每一个curd节点配置一个MappedStatement
对象
- 解析
- 解析配置的属性元素,例如
- 解析
- 获取
SqlSession
—>sqlSessionFactory.openSession(xxxx)
- 事务
TransactionFactory
- 执行器
Executor
new DefaultSqlSession(configuration, executor, autoCommit)
- 执行
mybatis
方法 ——>performDataDao.selectPerformDataByKey(1234571443)
- 获取对应
statementId
的MappedStatement
对象委托给executor#query
继续执行 - 跳过缓存,查询db,获取
PreparedStatementHandler
,执行预编译,设置参数- 预编译
connection.prepareStatement(sql)
—-> PreparedStatementHandler#instantiateStatement - 设置参数
preparedStatement.setInt(1, 1);
—-> DefaultParameterHandler#setParameters,将包转过的参数根据parameterType/Map设置
- 预编译
- 执行查询,处理结果集合
- 反射获取 pojo 对象,填充参数
- 获取对应
整个流程不算清晰,但是也能大致的说明 mybatis
的执行过程,具体可分为 解析配置文件
请求处理器
请求处理后
- 解析配置文件
configuration.xml 和 mapper,xml
,configuration
对象的参数填充MappedStatement
对象的填充,Resultmap 解析,Sql 节点解析 等等
- 请求处理前
- 预编译,设置参数,设置超时时间,设置fetchSize,设置ResultSetType
- 请求处理后
- 处理结果集,
RowBound
处理,ResultMap处理(反射pojo,参数填充)
- 处理结果集,
解析配置文件
请求处理前
请求处理后
小结
2018-10-22