list解析 mybatis_mybatis-session.selectList源码分析

0.构建工厂:SqlSessionFactory 。 new SqlSessionFactoryBuilder.build(配置的xml文件)

获取sqlSession对象

//指定事务隔离级别

1. sqlMapper.openSession(TransactionIsolationLevel.SERIALIZABLE)

openSession->openSessionFromDataSource->DefaultSqlSession

openSession->getTransactionFactoryFromEnvironment

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {

Transaction tx = null;

try {

final Environment environment = configuration.getEnvironment();

final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);

//通过事务工厂来产生一个事务

tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);

//生成一个执行器(事务包含在执行器里)

final Executor executor = configuration.newExecutor(tx, execType);

//然后产生一个DefaultSqlSession

return new DefaultSqlSession(configuration, executor, autoCommit);

} catch (Exception e) {

//如果打开事务出错,则关闭它

closeTransaction(tx); // may have fetched a connection so lets call close()

throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);

} finally {

//最后清空错误上下文

ErrorContext.instance().reset();

}

}

创建执行器 Executor (BatchExecutor,ReuseExecutor,SimpleExecutor,CachingExecutor)

默认是有缓存的,返回SimpleExecutor,并使用插件plugin,可以用来改变executor的行为

返回DefaultSqlSession;

使用sqlSession中对应的方法

2. session.selectList(指定的Mapper中的方法eg:selectAllAuthors)

selectList->executor.query->query

selectList-> configuration.getMappedStatement(statement)

public List selectList(String statement, Object parameter, RowBounds rowBounds) {

try {

//根据statement id找到对应的MappedStatement

MappedStatement ms = configuration.getMappedStatement(statement);

//转而用执行器来查询结果,注意这里传入的ResultHandler是null

return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);

} catch (Exception e) {

throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);

} finally {

ErrorContext.instance().reset();

}

}

public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {

//先构建所有语句,再返回语句

if (validateIncompleteStatements) {

buildAllStatements();

}

return mappedStatements.get(id);

}

public MappedStatement getMappedStatement(String id) {

return this.getMappedStatement(id, true);

}

query->ms.getBoundSql->sqlSource.getBoundSql

query->createCacheKey

query->query(ms, parameterObject, rowBounds, resultHandler, key, boundSql)

public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {

BoundSql boundSql = ms.getBoundSql(parameterObject);

//query时传入一个cachekey参数

CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);

return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

}

public BoundSql getBoundSql(Object parameterObject) {

//其实就是调用sqlSource.getBoundSql

BoundSql boundSql = sqlSource.getBoundSql(parameterObject);

//剩下的可以暂时忽略

List 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;

}

public BoundSql getBoundSql(Object parameterObject) {

return new BoundSql(configuration, sql, parameterMappings, parameterObject);

}

//创建缓存Key

public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {

if (closed) {

throw new ExecutorException("Executor was closed.");

}

CacheKey cacheKey = new CacheKey();

//MyBatis 对于其 Key 的生成采取规则为:[mappedStementId + offset + limit + SQL + queryParams + environment]生成一个哈希码

cacheKey.update(ms.getId());

cacheKey.update(Integer.valueOf(rowBounds.getOffset()));

cacheKey.update(Integer.valueOf(rowBounds.getLimit()));

cacheKey.update(boundSql.getSql());

List parameterMappings = boundSql.getParameterMappings();

TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();

// mimic DefaultParameterHandler logic

//模仿DefaultParameterHandler的逻辑,不再重复,请参考DefaultParameterHandler

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.hasAdditionalParameter(propertyName)) {

value = boundSql.getAdditionalParameter(propertyName);

} else if (parameterObject == null) {

value = null;

} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {

value = parameterObject;

} else {

MetaObject metaObject = configuration.newMetaObject(parameterObject);

value = metaObject.getValue(propertyName);

}

cacheKey.update(value);

}

}

if (configuration.getEnvironment() != null) {

// issue #176

cacheKey.update(configuration.getEnvironment().getId());

}

return cacheKey;

}

query-> delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql)

public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)

throws SQLException {

Cache cache = ms.getCache();

//默认情况下是没有开启缓存的(二级缓存).要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:

//简单的说,就是先查CacheKey,查不到再委托给实际的执行器去查

if (cache != null) {

flushCacheIfRequired(ms);

if (ms.isUseCache() && resultHandler == null) {

ensureNoOutParams(ms, parameterObject, boundSql);

@SuppressWarnings("unchecked")

List list = (List) tcm.getObject(cache, key);

if (list == null) {

list = delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

tcm.putObject(cache, key, list); // issue #578 and #116

}

return list;

}

}

return delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

}

query-> queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql)

@SuppressWarnings("unchecked")

@Override

public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {

ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());

//如果已经关闭,报错

if (closed) {

throw new ExecutorException("Executor was closed.");

}

//先清局部缓存,再查询.但仅查询堆栈为0,才清。为了处理递归调用

if (queryStack == 0 && ms.isFlushCacheRequired()) {

clearLocalCache();

}

List list;

try {

//加一,这样递归调用到上面的时候就不会再清局部缓存了

queryStack++;

//先根据cachekey从localCache去查

list = resultHandler == null ? (List) localCache.getObject(key) : null;

if (list != null) {

//若查到localCache缓存,处理localOutputParameterCache

handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);

} else {

//从数据库查

list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);

}

} finally {

//清空堆栈

queryStack--;

}

if (queryStack == 0) {

//延迟加载队列中所有元素

for (DeferredLoad deferredLoad : deferredLoads) {

deferredLoad.load();

}

// issue #601

//清空延迟加载队列

deferredLoads.clear();

if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {

// issue #482

//如果是STATEMENT,清本地缓存

clearLocalCache();

}

}

return list;

}

queryFromDatabase->doQuery

//从数据库查

private List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {

List list;

//先向缓存中放入占位符???

localCache.putObject(key, EXECUTION_PLACEHOLDER);

try {

list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);

} finally {

//最后删除占位符

localCache.removeObject(key);

}

//加入缓存

localCache.putObject(key, list);

//如果是存储过程,OUT参数也加入缓存

if (ms.getStatementType() == StatementType.CALLABLE) {

localOutputParameterCache.putObject(key, parameter);

}

return list;

}

StatementHandler,

ResultSetHandler,

RoutingStatementHandler,

BaseStatementHandler,

PreparedStatementHandler

@Override

public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {

Statement stmt = null;

try {

Configuration configuration = ms.getConfiguration();

//新建一个StatementHandler

//这里看到ResultHandler传入了

StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);

//准备语句

stmt = prepareStatement(handler, ms.getStatementLog());

//StatementHandler.query

return handler.query(stmt, resultHandler);

} finally {

closeStatement(stmt);

}

}

Configuration

//创建结果集处理器

public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,

ResultHandler resultHandler, BoundSql boundSql) {

//创建DefaultResultSetHandler(稍老一点的版本3.1是创建NestedResultSetHandler或者FastResultSetHandler)

ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);

//插件在这里插入

resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);

return resultSetHandler;

}

路由选择语句

public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {

//根据语句类型,委派到不同的语句处理器(STATEMENT|PREPARED|CALLABLE)

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());

}

}

BaseStatementHandler 语句处理类

//准备语句

@Override

public Statement prepare(Connection connection) throws SQLException {

ErrorContext.instance().sql(boundSql.getSql());

Statement statement = null;

try {

//实例化Statement

statement = instantiateStatement(connection);

//设置超时

setStatementTimeout(statement);

//设置读取条数

setFetchSize(statement);

return statement;

} catch (SQLException e) {

closeStatement(statement);

throw e;

} catch (Exception e) {

closeStatement(statement);

throw new ExecutorException("Error preparing statement. Cause: " + e, e);

}

}

PreparedStatementHandler

@Override

protected Statement instantiateStatement(Connection connection) throws SQLException {

//调用Connection.prepareStatement

String sql = boundSql.getSql();

if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {

String[] keyColumnNames = mappedStatement.getKeyColumns();

if (keyColumnNames == null) {

return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);

} else {

return connection.prepareStatement(sql, keyColumnNames);queryFromDatabase

}

} else if (mappedStatement.getResultSetType() != null) {

return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);

} else {

return connection.prepareStatement(sql);

}

}

转载至链接:https://my.oschina.net/iioschina/blog/1859699

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值