1. 从selectList看Mybatis中一个sql 是如何
- 首页https://www.jianshu.com/p/39106eac8081
- Configuration https://www.jianshu.com/p/97522192011b
- DynamicSqlSource https://www.jianshu.com/p/2938876957ab
- PreparedStatement https://www.jianshu.com/p/5979f2514af3
- Parameter https://www.jianshu.com/p/8b93b0b1b7cf
- InterceptorChainhttps://www.jianshu.com/p/2d28f7c1a780
- StatementHandler https://www.jianshu.com/p/e82e846ac680
- ResultSetHandler https://www.jianshu.com/p/63d61dda0f25
致敬作者[克林顿·贝京]
Clinton Begin is a Senior Developer and Agile Mentor for ThoughtWorks Canada. He has been building enterprise applications for nine years based on platforms such as Java and .NET. Clinton has extensive experience with agile methodologies, persistence frameworks, and relational databases. He is the original creator of the iBATIS persistence framework, which he designed in response to the challenges faced by object oriented developers dealing with enterprise relational databases
这是一张ibatis的结构图, 略做参考
image@see https://www.ibm.com/developerworks/cn/java/j-lo-ibatis-principle/index.html
一个SQL的执行过程
由configuration解析,获取MappedStatement, variables
由SqlSession的executor 最终执行
sql参数
sql
一个典型的SQL, 由statement,parameter,RowBounds(分页参数)组成
如下:
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds)
一个典型的statement
<select id="queryById" resultType= ..>
statement由注解或xml生成, 由configuration管理
configuration.getMappedStatement(statement)
MappedStatement getMappedStatement(String id)
configuration详见configuration章节
MappedStatement由XML/... StatementBuilder 产生
paramter
查询参数 详见paramter章节
BoundSql
可以看到BoundSql由sqlSource获取到. sqlSource有若干实现类, 包含我们常见的xml SqlSource, 还有annotation SqlSource
DynamicSqlSource 详见DynamicSqlSource 章节
public BoundSql getBoundSql(Object parameterObject) {
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings == null || parameterMappings.isEmpty()) {
boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
}
// check for nested result maps in parameter mappings (issue #30)
for (ParameterMapping pm : boundSql.getParameterMappings()) {
String rmId = pm.getResultMapId();
if (rmId != null) {
ResultMap rm = configuration.getResultMap(rmId);
if (rm != null) {
hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
}
return boundSql;
}
rowbounds
分页参数,见 rowbounds章节
sql执行
Mybatis Sql执行由Executor负责
org.apache.ibatis.executor.Executor
每个SqlSession需要注入executor
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
Configuration如无特殊指定,采用的是SimpleExecutor
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
四个executor网上对比很多, SimpleExecutor每次都会采用新用statement, 性能稍差, 但ReuseExecutor由于是session级别的, 性能提升有限.
doQuery sql执行
interceptorChain 参见interceptorChain
public <E> List<E> 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);
}
}
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;
}