MyBatis 源码解读:深入理解MyBatis工作原理

一、引言
MyBatis 是一款优秀的持久层框架,它消除了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。MyBatis 通过简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
本文将深入解读 MyBatis 源码,帮助你更好地理解 MyBatis 的工作原理,从而在实际开发中更好地运用 MyBatis。
二、MyBatis 核心组件
1. SqlSessionFactoryBuilder:构建 SqlSessionFactory 的工厂类。
2. SqlSessionFactory:SqlSession 的工厂接口,用于创建 SqlSession。
3. SqlSession:MyBatis 的核心接口,负责执行 SQL、管理事务等。
4. Executor:MyBatis 执行器,负责执行 SQL 语句。
5. StatementHandler:MyBatis 的 SQL 执行器,负责执行 SQL 语句。
6. ParameterHandler:MyBatis 的参数处理器,负责处理 SQL 语句中的参数。
7. ResultSetHandler:MyBatis 的结果集处理器,负责处理查询结果。
8. Mapper:MyBatis 的映射接口,用于定义 SQL 语句。
三、MyBatis 的工作流程
1. 加载 MyBatis 配置文件(XML 或注解)
2. 创建 SqlSessionFactoryBuilder
3. 创建 SqlSessionFactory
4. 创建 SqlSession
5. 执行 SQL 语句
6. 关闭 SqlSession
四、MyBatis 源码解读
1. SqlSessionFactoryBuilder
SqlSessionFactoryBuilder 是 MyBatis 的入口,用于构建 SqlSessionFactory。
```java
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();
}
}
```
2. SqlSessionFactory
SqlSessionFactory 负责创建 SqlSession。
```java
public SqlSession openSession() {
return openSessionFromDataSource(executorType, Level.Nested, AutoCommitSettings.TRUE);
}
public SqlSession openSession(ExecutorType execType) {
return openSessionFromDataSource(execType, Level.Nested, AutoCommitSettings.TRUE);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, AutoCommitSettings autoCommit) {
try {
Configuration configuration = config;
Executor executor = configuration.newExecutor(execType, transactionManager, level, autoCommit);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
}
}
```
3. SqlSession
SqlSession 负责执行 SQL 语句和管理事务。
```java
public
checkCustom resultMap();
return mapperProxy.executeSqlSession(this, statement, parameter);
}
public
checkCustom resultMap();
return mapperProxy.executeSqlSession(this, statement, parameter);
}
public
checkCustom resultMap();
return mapperProxy.executeSqlSession(this, statement, parameter);
}
```
4. Executor
Executor 负责执行 SQL 语句。
```java
public
if (ms.isFlushCacheRequired()) {
clearLocalCache();
}
Query query = queryCache.getQuery(ms, parameter, rowBounds, this);
List
boolean noCache = ms.isUseCache() && (query == null);
if (noCache) {
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} else {
CacheKey key = query.getKey();
List
list = (noCache) ? doQuery(ms, parameter, rowBounds, resultHandler, boundSql) : addToList(cachedList);
}
if (ms.isUseCache()) {
queryCache.putQuery(ms, parameter, rowBounds, list);
}
return list;
}
```
5. StatementHandler
StatementHandler 负责执行 SQL 语句。
```java
public
final BoundSql boundSql = statement.getBoundSql(this);
CacheKey key = createCacheKey(boundSql, this.objectFactory);
if (configuration.getEnvironment().getSqlSession().getLocalCacheScope() == LocalCacheScope.STATEMENT) {
return queryFromCache(key, boundSql, statement);
} else {
return queryFromDatabase(key, boundSql, statement);
}
}
```
6. ParameterHandler
ParameterHandler 负责处理 SQL 语句中的参数。
```java
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(this.boundSql.getParameterObject());
List
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameters()) {
value = boundSql.getAdditionalParameter(propertyName);
if (value == null) {
value = parameterObject;
}
} else {
value = parameterObject;
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new BindingException("Type handler not found for parameter '" + propertyName + "' for property '" + parameterMapping.getProperty() + "'");
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}
}
```
7. ResultSetHandler
ResultSetHandler 负责处理查询结果。
```java
public
final List
final DefaultResultSetHandler defaultResultSetHandler = (DefaultResultSetHandler) handler;
final ResultSet resultSet = handler.getResultSet();
final ResultSetHandler resultSetHandler = resultHandler == null ? defaultResultSetHandler : resultHandler;
try {
list = resultSetHandler.handleResultSets(handler);
} finally {
closeResultSet(resultSet);
}
return list;
}
```
五、总结
通过以上对 MyBatis 源码的解读,我们深入了解了 MyBatis 的工作原理。在实际开发中,了解 MyBatis 的内部机制,有助于我们更好地解决开发过程中遇到的问题,提高开发效率。
在接下来的开发中,我们可以根据实际需求,对 MyBatis 进行扩展和定制,以满足项目的需求。同时,了解 MyBatis 的内部机制,也有助于我们更好地优化 SQL 语句,提高数据库性能。
总之,掌握 MyBatis 源码,对于提升我们的编程技能和解决实际问题是大有裨益的。希望本文能对你有所帮助!





