Mybatis核心类讲解

SqlSessionFactoryBuilder
每一个MyBatis的应用程序的入口是SqlSessionFactoryBuilder。它的作用是通过XML配置文件创建Configuration对象,然后通过build方法创建SqlSessionFactory对象。可以做到全局只有一个就行。不需要每次都创建。
SqlSessionFactory
SqlSessionFactory的主要功能是创建SqlSession对象,和SqlSessionFactoryBuilder对象一样,没有必要每次访问Mybatis就创建一次SqlSessionFactory,通常的做法是创建一个全局的对象就可以了。
SqlSession
SqlSession类的主要功能是完成一次数据库的访问和结果的映射,它类似于一次会话概念,顾命名为:SqlSession。
SqlSession类似于JDBC里面的Connection,Connection不是线程安全的,SqlSession也不是线程安全的。由于不是线程安全的,所以SqlSession对象的作用域需限制方法内。
SqlSession的默认实现类是DefaultSqlSession,它有两个必须配置的属性:Configuration和Executor。mybatis-config.xml中的配置,最后会解析xml成Configuration这个类。SqlSession对数据库的操作都是通过Executor来完成的。
SqlSession有一个重要的方法getMapper,顾名思义,这个方式是用来获取Mapper映射器的。
SqlSession有很多增删改查的方法。
Executor

BaseExecutor: BaseExecutor是一个抽象类,采用模板方法的设计模式。它实现了Executor接口,实现了执行器的基本功能。具体使用哪一个Executor则是可以在 mybatis 的 config.xml 中进行配置的。默认为SimpleExecutor;
**SimpleExecutor:**最简单的执行器,根据对应的sql直接执行即可,不会做一些额外的操作;
BatchExecutor: 通过批量操作来优化性能。通常需要注意的是批量更新操作,由于内部有缓存的实现,使用完成后记得调用flushStatements来清除缓存。
**ReuseExecutor :**重用的执行器,重用的对象是Statement,也就是说该执行器会缓存同一个sql的Statement,省去Statement的重新创建,优化性能。内部的实现是通过一个HashMap来维护Statement对象的。由于当前Map只在该session中有效,所以使用完成后记得调用flushStatements来清除Map。调用实现的四个抽象方法时会调用 prepareStatement() ;
**CachingExecutor:**启用于二级缓存时的执行器;采用静态代理;代理一个 Executor 对象。执行 update 方法前判断是否清空二级缓存;执行 query 方法前先在二级缓存中查询,命中失败再通过被代理类查询。
**ClosedExecutor:**也继承了BaseExecutor抽象类,且是ResultLoaderMap类中的一个内部类,用于实现懒加载相关逻辑
/**
* 执行器
* @author Clinton Begin
*/
public interface Executor {
ResultHandler NO_RESULT_HANDLER = null;
// insert | update | delete 语句执行
int update(MappedStatement ms, Object parameter) throws SQLException;
// select
<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
// select
<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
// select 返回游标
<E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
// 批量
List<BatchResult> flushStatements() throws SQLException;
// 提交事务
void commit(boolean required) throws SQLException;
// 回滚
void rollback(boolean required) throws SQLException;
// 创建缓存中使用的 CacheKey
CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
// 根据 CacheKey 查找缓存
boolean isCached(MappedStatement ms, CacheKey key);
// 清空一级缓存
void clearLocalCache();
// 延迟加载一级缓存中的数据
void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
// 获取事务
Transaction getTransaction();
// 关闭 Executor 对象
void close(boolean forceRollback);
// 是否已经关闭
boolean isClosed();
void setExecutorWrapper(Executor executor);
}
Executor对象在创建Configuration对象的时候创建,并且缓存在Configuration对象里。
Executor对象的主要功能是调用StatementHandler访问数据库。
StatementHandler

BaseStatementHandler:是 StatementHandler 接口的另一个实现类.本身是一个抽象类.用于简化StatementHandler 接口实现的难度,属于适配器设计模式体现,它主要有三个实现类
SimpleStatementHandler: 管理 Statement 对象并向数据库中推送不需要预编译的SQL语句
PreparedStatementHandler: 管理 Statement 对象并向数据中推送需要预编译的SQL语句,
CallableStatementHandler:管理 Statement 对象并调用数据库中的存储过程
**RoutingStatementHandler:**RoutingStatementHandler 并没有对 Statement 对象进行使用,只是根据StatementType 来创建一个代理,代理的就是上述的三种实现类。
/**
* 使用了策略模式的一个 StatementHandler 实现, 其最终调用的是实际 StatementHandler 的方法
*/
public class RoutingStatementHandler implements StatementHandler {
// 真正的 Statement 对象
private final StatementHandler delegate;
/**
* 根据指定的类型,创建对应的接口实现
*/
public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED:
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case CALLABLE:
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
/**
* 核心类, 与执行相关
*/
public interface StatementHandler {
// 从连接中获取一个 statement
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;
// 绑定 statement 执行时所需要的参数
void parameterize(Statement statement)
throws SQLException;
// 批量
void batch(Statement statement)
throws SQLException;
// update|delete|insert
int update(Statement statement)
throws SQLException;
// 查询 select
<E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException;
// 游标查询
<E> Cursor<E> queryCursor(Statement statement)
throws SQLException;
// 获取绑定的 sql
BoundSql getBoundSql();
// 获取封装的 PrameterHandler
ParameterHandler getParameterHandler();
}
StatementHandler对象的创建
StatementHandler 对象是在 SqlSession 对象接收到命令操作时,由 Configuration 对象中的newStatementHandler 负责调用的,也就是说 Configuration 中的 newStatementHandler 是由执行器中的查询、更新(插入、更新、删除)方法来提供的,StatementHandler 其实就是由 Executor 负责管理和创建的。
/**
* 简单Executor实现类
*/
public class SimpleExecutor extends BaseExecutor {
public SimpleExecutor(Configuration configuration, Transaction transaction) {
super(configuration, transaction);
}
/**
* 更新(insert | udpdate | delete)实现
* @param ms
* @param parameter
* @return
* @throws SQLException
*/
@Override
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
try {
// 获取配置
Configuration configuration = ms.getConfiguration();
// 获取 StatementHandler
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
// 准备 Statement
stmt = prepareStatement(handler, ms.getStatementLog());
// 执行
return handler.update(stmt);
} finally {
// 关闭
closeStatement(stmt);
}
}
/**
* 查询
*/
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
// 使用 Statement
Statement stmt = null;
try {
// 获取配置对象
Configuration configuration = ms.getConfiguration();
// 获取对应的 StatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
// Statement 初始化
stmt = prepareStatement(handler, ms.getStatementLog());
// 查询并完成结果映射
return handler.<E>query(stmt, resultHandler);
} finally {
// 关闭
closeStatement(stmt);
}
}
/**
* 查询, 游标
*/
@Override
protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql);
Statement stmt = prepareStatement(handler, ms.getStatementLog());
return handler.<E>queryCursor(stmt);
}
/**
* 返回空集合, 即不处理批处理
*/
@Override
public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
return Collections.emptyList();
}
//2、prepareStatement()
/**
* 准备 Statement
* @param handler
* @param statementLog
* @return
* @throws SQLException
*/
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
// 获取连接
Connection connection = getConnection(statementLog);
// 调用 handler.prepare() 创建 Statement 对象
stmt = handler.prepare(connection, transaction.getTimeout());
// 处理占位符
handler.parameterize(stmt);
return stmt;
}
}
//1、configuration.newStatementHandler()
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
- 源代码可以看出StatementHandler 默认创建一个 RoutingStatementHandler ,这也就是 StatementHandler 的默认实现,由 RoutingStatementHandler 负责根据 StatementType 创建对应的StatementHandler 来处理调用。而且也会走拦截器调用链。
- 通过
prepareStatement()方法,先是获取到数据库连接,然后通过调用链可以看到会去调用instantiateStatement()方法,instantiateStatement 方法位于 StatementHandler 中,是一个抽象方法由子类去实现,实际执行的是三种 StatementHandler 中的一种,我们还以SimpleStatementHandler为例
/**
* 初始化 Statement 对象, 通过 Connection 进行创建
*/
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
return connection.createStatement();
} else {
return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
经过一系列的调用会把statement 对象返回到 SimpleExecutor 简单执行器中,为 parametersize 方法所用。
但是这个时候看到SimpleStatementHandler里面的parameterize 是一个空实现。原因是因为:SimpleStatementHandler 只负责处理简单SQL,能够直接查询得到结果的SQL,例如:select a from b 。SimpleStatementHandler不涉及参数赋值的问题,所以这个时候应该看**PreparedStatementHandler**
- 通过
*org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters*绑定具体的参数 - 执行查询或者更新语句。根据不同的执行器对象使用不同的statement执行sql语句。
org.apache.ibatis.executor.statement.SimpleStatementHandler#query
/**
* 查询
*/
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
// 获取 SQL 语句
String sql = boundSql.getSql();
// 执行 SQL 语句
statement.execute(sql);
// 处理结果集
return resultSetHandler.<E>handleResultSets(statement);
}
org.apache.ibatis.executor.statement.PreparedStatementHandler#query
/**
* 查询
*/
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
org.apache.ibatis.executor.statement.CallableStatementHandler#query
/**
* 查询
*/
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
CallableStatement cs = (CallableStatement) statement;
cs.execute();
List<E> resultList = resultSetHandler.<E>handleResultSets(cs);
resultSetHandler.handleOutputParameters(cs);
return resultList;
}
ResultSetHandler
/**
* 结果集处理 只有一个实现类 org.apache.ibatis.executor.resultset.DefaultResultSetHandler
*/
public interface ResultSetHandler {
// 处理生成的结果集
<E> List<E> handleResultSets(Statement stmt) throws SQLException;
// 梳理结果集, 返回相应的游标对象
<E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;
// 处理存储过程的输出函数
void handleOutputParameters(CallableStatement cs) throws SQLException;
}
这个类也是比较复杂的一个,除了正常的对象属性映射,还需要处理一对一,一对多的。

TypeHandler
负责Java数据类型和JDBC数据类型之间的映射和转换。Mybatis内置了很多类型处理器(TypeHandlerRegistry )自己也可以自定类型处理器。
SqlSource
负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回。
BoundSql
表示动态生成的SQL语句以及相应的参数信息
Configuration
MyBatis所有的配置信息都维持在Configuration对象之中


被折叠的 条评论
为什么被折叠?



