能说说MyBatis的工作原理吗?

能说说MyBatis的工作原理吗?
我们已经大概知道了MyBatis的工作流程,按工作原理,可以分为两大步:生成会话工厂
、会话运行
。
MyBatis是一个成熟的框架,篇幅限制,这里抓大放小,来看看它的主要工作流程。
构建会话工厂
- 获取配置
获取配置这一步经过了几步转化,最终由生成了一个配置类Configuration实例,这个配置类实例非常重要,主要作用包括:
- 读取配置文件,包括基础配置文件和映射文件
- 初始化基础配置,比如MyBatis的别名,还有其它的一些重要的类对象,像插件、映射器、ObjectFactory等等
- 提供一个单例,作为会话工厂构建的重要参数
- 它的构建过程也会初始化一些环境变量,比如数据源
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
SqlSessionFactory var5;
//省略异常处理
//xml配置构建器
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
//通过转化的Configuration构建SqlSessionFactory
var5 = this.build(parser.parse());
}
- 构建SqlSessionFactory
SqlSessionFactory只是一个接口,构建出来的实际上是它的实现类的实例,一般我们用的都是它的实现类DefaultSqlSessionFactory,
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
会话运行
会话运行是MyBatis最复杂的部分,它的运行离不开四大组件的
- Executor(执行器)
Executor起到了至关重要的作用,SqlSession只是一个门面,相当于客服,真正干活的是是Executor,就像是默默无闻的工程师。它提供了相应的查询和更新方法,以及事务方法。
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//通过Configuration创建executor
Executor executor = this.configuration.newExecutor(tx, execType);
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
- StatementHandler(数据库会话器)
StatementHandler,顾名思义,处理数据库会话的。我们以SimpleExecutor为例,看一下它的查询方法,先生成了一个StatementHandler实例,再拿这个handler去执行query。
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
List var9;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this.wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = this.prepareStatement(handler, ms.getStatementLog());
var9 = handler.query(stmt, resultHandler);
} finally {
this.closeStatement(stmt);
}
return var9;
}
再以最常用的PreparedStatementHandler看一下它的query方法,其实在上面的prepareStatement
已经对参数进行了预编译处理,到了这里,就直接执行sql,使用ResultHandler处理返回结果。
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement)statement;
ps.execute();
return this.resultSetHandler.handleResultSets(ps);
}
- ParameterHandler (参数处理器)
PreparedStatementHandler里对sql进行了预编译处理
public void parameterize(Statement statement) throws SQLException {
this.parameterHandler.setParameters((PreparedStatement)statement);
}
这里用的就是ParameterHandler,setParameters的作用就是设置预编译SQL语句的参数。
里面还会用到typeHandler类型处理器,对类型进行处理。
public interface ParameterHandler {
Object getParameterObject();
void setParameters(PreparedStatement var1) throws SQLException;
}
- ResultSetHandler(结果处理器)
我们前面也看到了,最后的结果要通过ResultSetHandler来进行处理,handleResultSets这个方法就是用来包装结果集的。Mybatis为我们提供了一个DefaultResultSetHandler,通常都是用这个实现类去进行结果的处理的。
public interface ResultSetHandler {
<E> List<E> handleResultSets(Statement var1) throws SQLException;
<E> Cursor<E> handleCursorResultSets(Statement var1) throws SQLException;
void handleOutputParameters(CallableStatement var1) throws SQLException;
}
整体工作流程如下:
- 读取MyBatis的配置文件(mybatis-config.xml)和映射文件(SQL映射文件),生成配置对象。
- 构建会话工厂(SqlSessionFactory):使用配置对象,创建会话工厂,会话工厂是生成会话(SqlSession)的工厂类。
- 创建会话(SqlSession):通过会话工厂创建会话对象,会话对象包含执行SQL语句的方法。
- 执行器(Executor):会话对象使用执行器来操作数据库。执行器根据传递的参数动态生成需要执行的SQL语句,并负责查询缓存的管理。
- 语句处理器(StatementHandler):负责处理SQL语句的参数映射和结果映射,将参数传递给数据库并执行SQL语句。
- 参数处理:处理输入参数的类型,并进行预编译。
- 结果处理:根据对象映射规则,将数据库返回的结果映射为相应的对象。