MyBatis原理(2)-执行流程 2


@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
}



BaseExecutor#createCacheKey

@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {[size=x-small][/size]
if (closed) {
throw new ExecutorException("Executor was closed.");
}
CacheKey cacheKey = new CacheKey();
cacheKey.update(ms.getId());
cacheKey.update(rowBounds.getOffset());
cacheKey.update(rowBounds.getLimit());
cacheKey.update(boundSql.getSql());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
for (ParameterMapping parameterMapping : parameterMappings) {
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;
}

根据参数值,RowBounds,ParameterMapping确定缓存Key,每次update会更新Cachekey中的属性,equals的时候会比较各个字段的值,如果两次查询所传入的参数值,ParameterMapping都相等那么就是相同的cacheKey。

public void update(Object object) {
int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);

count++;
checksum += baseHashCode;
baseHashCode *= count;

hashcode = multiplier * hashcode + baseHashCode;

updateList.add(object);
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof CacheKey)) {
return false;
}

final CacheKey cacheKey = (CacheKey) object;

if (hashcode != cacheKey.hashcode) {
return false;
}
if (checksum != cacheKey.checksum) {
return false;
}
if (count != cacheKey.count) {
return false;
}

for (int i = 0; i < updateList.size(); i++) {
Object thisObject = updateList.get(i);
Object thatObject = cacheKey.updateList.get(i);
if (!ArrayUtil.equals(thisObject, thatObject)) {
return false;
}
}
return true;
}


createCacheKey方法在Excutor接口定义由BaseExecutor实现,Executor接口的继承接口如下:
[img]
http://my.iteye.com/admin/picture/138355
[/img]
除CachingExecutor之外直接实现Excutor,其他接口均是继承自BaseExcutor,而CachingExecutor只是对其他Executor进行包装:

public class CachingExecutor implements Executor {

private final Executor delegate;
//二级事务缓存
private final TransactionalCacheManager tcm = new TransactionalCacheManager();

public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}




@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
//此处获取的是SynchronizedCache的实例,在装饰的对象缓存方法加上Synchronized,二级缓存
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
//只有对结果处理器为空的才使用二级缓存 //TODO为什么
if (ms.isUseCache() && resultHandler == null) {
//parameterMapping只允许存在IN类型的参数映射
ensureNoOutParams(ms, boundSql);
@SuppressWarnings("unchecked")
//获取事务缓存(二级缓存//TODO)
List<E> list = (List<E>) tcm.getObject(cache, key);
//缓存为空则委托子类(SimpleExecutor查询),否则直接返回二级缓存结果
if (list == null) {
//BaseExecutor#query
list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);


}

此处获取默认缓存是SynchronizedCache,原因是在XMLMapperBuilder#cacheElement解析<cache>节点构建缓存,调用BuilderAssistant#useNewCache,下面是构建缓存链的几个重要的流程:

public Cache useNewCache(Class<? extends Cache> typeClass,
Class<? extends Cache> evictionClass,
Long flushInterval,
Integer size,
boolean readWrite,
boolean blocking,
Properties props) {
//缓存id为当前xml命名空间
Cache cache = new CacheBuilder(currentNamespace)
//没指定实现默认使用PerpetualCache,内部是HashMap
.implementation(valueOrDefault(typeClass, PerpetualCache.class))
//没指定过期装饰器默认使用最近最少使用LRUCache对PerpetualCache进行装饰
.addDecorator(valueOrDefault(evictionClass, LruCache.class))
.clearInterval(flushInterval)
.size(size)
.readWrite(readWrite)
.blocking(blocking)
.properties(props)
.build();
//添加到配置configuration
configuration.addCache(cache);
//设置当前缓存以便为MapperStatement使用
currentCache = cache;
return cache;
}


public Cache build() {
setDefaultImplementations();
//构造PerpetualCache
Cache cache = newBaseCacheInstance(implementation, id);
setCacheProperties(cache);
// issue #352, do not apply decorators to custom caches
if (PerpetualCache.class.equals(cache.getClass())) {
//添加底层基础装饰器PerpetualCache为第一层,LruCache为第二层
for (Class<? extends Cache> decorator : decorators) {

cache = newCacheDecoratorInstance(decorator, cache);
//给LruCache设置相应属性,主要是size,默认1024
setCacheProperties(cache);
}
//设置装饰器链
cache = setStandardDecorators(cache);
} else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
cache = new LoggingCache(cache);
}
return cache;
}
//设置默认实现和默认最下层的装饰器
private void setDefaultImplementations() {
if (implementation == null) {
implementation = PerpetualCache.class;
if (decorators.isEmpty()) {
decorators.add(LruCache.class);
}
}
}

private Cache setStandardDecorators(Cache cache) {
try {
//再次检查是否设置上
MetaObject metaCache = SystemMetaObject.forObject(cache);
if (size != null && metaCache.hasSetter("size")) {
metaCache.setValue("size", size);
}
if (clearInterval != null) {
//添加过期feature
cache = new ScheduledCache(cache);
((ScheduledCache) cache).setClearInterval(clearInterval);
}
if (readWrite) {
//开启readWrite只能将实现了Serializable的对象添加到缓存
cache = new SerializedCache(cache);
}
//日志记录缓存命中率
cache = new LoggingCache(cache);
//给缓存中add put size方法加上 SynchronizedCache
cache = new SynchronizedCache(cache);
if (blocking) {
//blocking=true,是否阻塞
//每一个key都对应一把锁,当get的时候请求锁,延迟时间后未获取到锁抛出异常
cache = new BlockingCache(cache);
}
return cache;
} catch (Exception e) {
throw new CacheException("Error building standard cache decorators. Cause: " + e, e);
}
}




private void flushCacheIfRequired(MappedStatement ms) {
//二级缓存
Cache cache = ms.getCache();
//MapperBuilderAssistant#292
// .flushCacheRequired(valueOrDefault(flushCache, !isSelect))
//如果没有设置了flushCache ,则查询语句都是默认开启二级缓存,即不清除
if (cache != null && ms.isFlushCacheRequired()) {
//flushCache=true或者是不是select
//清除当前缓存
tcm.clear(cache);
}
}

单独解释下 tcm.clear(cache)
tcm是CachingExecutor的实例变量也是CachingExecutor被叫做CachingExecutor的原因,既然说到了缓存也说下CachingExecutor:

public class CachingExecutor implements Executor {

private final Executor delegate;
private final TransactionalCacheManager tcm = new TransactionalCacheManager();

public CachingExecutor(Executor delegate) {
this.delegate = delegate;
delegate.setExecutorWrapper(this);
}

@Override
public Transaction getTransaction() {
return delegate.getTransaction();
}

@Override
public void close(boolean forceRollback) {
try {
//issues #499, #524 and #573
if (forceRollback) {
tcm.rollback();
} else {
tcm.commit();
}
} finally {
delegate.close(forceRollback);
}
}

@Override
public boolean isClosed() {
return delegate.isClosed();
}

@Override
public int update(MappedStatement ms, Object parameterObject) throws SQLException {
flushCacheIfRequired(ms);
return delegate.update(ms, parameterObject);
}

@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
BoundSql boundSql = ms.getBoundSql(parameterObject);
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

@Override
public <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException {
flushCacheIfRequired(ms);
return delegate.queryCursor(ms, parameter, rowBounds);
}

@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
//二级缓存
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

@Override
public List<BatchResult> flushStatements() throws SQLException {
return delegate.flushStatements();
}

@Override
public void commit(boolean required) throws SQLException {
delegate.commit(required);
tcm.commit();
}

@Override
public void rollback(boolean required) throws SQLException {
try {
delegate.rollback(required);
} finally {
if (required) {
tcm.rollback();
}
}
}

private void ensureNoOutParams(MappedStatement ms, BoundSql boundSql) {
if (ms.getStatementType() == StatementType.CALLABLE) {
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
if (parameterMapping.getMode() != ParameterMode.IN) {
throw new ExecutorException("Caching stored procedures with OUT params is not supported. Please configure useCache=false in " + ms.getId() + " statement.");
}
}
}
}

@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
}

@Override
public boolean isCached(MappedStatement ms, CacheKey key) {
return delegate.isCached(ms, key);
}

@Override
public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
delegate.deferLoad(ms, resultObject, property, key, targetType);
}

@Override
public void clearLocalCache() {
delegate.clearLocalCache();
}
//是否有必要清除缓存,select语句不进行清除,或者表明当前查询需要进行清除
private void flushCacheIfRequired(MappedStatement ms) {
//这里获取的是二级缓存
Cache cache = ms.getCache();
if (cache != null && ms.isFlushCacheRequired()) {
tcm.clear(cache);
}
}

@Override
public void setExecutorWrapper(Executor executor) {
throw new UnsupportedOperationException("This method should not be called");
}

}


TransactionalCacheManager:缓存的事务管理器
TransactionalCacheManager被CachingExecutor持有,默认同一个SQLSession中,所有的
Cache(MapperStatement中的cache 二级缓存),都被这个缓存管理器管理

[code="java"]
public class TransactionalCacheManager {

private final Map<Cache, TransactionalCache> transactionalCaches = new HashMap<Cache, TransactionalCache>();
//清除某个mapper对应的cache或注解声明的cache对应的TransactionalCache
public void clear(Cache cache) {
getTransactionalCache(cache).clear();
}

public Object getObject(Cache cache, CacheKey key) {
return getTransactionalCache(cache).getObject(key);
}

public void putObject(Cache cache, CacheKey key, Object value) {
getTransactionalCache(cache).putObject(key, value);
}
//提交当前事务缓存
public void commit() {
for (TransactionalCache txCache : transactionalCaches.values()) {
txCache.commit();
}
}
//回滚所有事务缓存
public void rollback() {
for (TransactionalCache txCache : transactionalCaches.values()) {
txCache.rollback();
}
}

private TransactionalCache getTransactionalCache(Cache cache) {
TransactionalCache txCache = transactionalCaches.get(cache);
if (txCache == null) {
txCache = new TransactionalCache(cache);
transactionalCaches.put(cache, txCache);
}
return txCache;
}

}


事务缓存--应该叫缓存事务:TransactionalCache
为底层Cache增加事务功能,简单来说即commit和rollback功能。
commit即将entriesToAddOnCommit提交到底层缓存中,
rollback即回退

public class TransactionalCache implements Cache {

private static final Log log = LogFactory.getLog(TransactionalCache.class);
//包装类
private final Cache delegate;
//是否在提交的时候清除底层缓存
private boolean clearOnCommit;
//提交的时候要被添加到缓存中的对象
private final Map<Object, Object> entriesToAddOnCommit;
//未命中的对象
private final Set<Object> entriesMissedInCache;

public TransactionalCache(Cache delegate) {
this.delegate = delegate;
//默认false
this.clearOnCommit = false;
this.entriesToAddOnCommit = new HashMap<Object, Object>();
this.entriesMissedInCache = new HashSet<Object>();
}

@Override
public String getId() {
return delegate.getId();
}

@Override
public int getSize() {
return delegate.getSize();
}

@Override
public Object getObject(Object key) {
// issue #116
//底层缓存获取为空添加到entriesMissedInCache中
Object object = delegate.getObject(key);
if (object == null) {
entriesMissedInCache.add(key);
}
// issue #146
//If a session is closed with no commit/rollback, 2nd level caches should be updated if the session just executed selects
如果clearOnCommit为true即执行过clear,clear在CachingExcutor中flushCacheIfRequired调用,在调用update方法时flushCacheIfRequired返回true
if (clearOnCommit) {
return null;
} else {
return object;
}
}

@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
//放入entriesToAddOnCommit等待提交
@Override
public void putObject(Object key, Object object) {
entriesToAddOnCommit.put(key, object);
}

@Override
public Object removeObject(Object key) {
return null;
}

//清除待提交,设置标志
@Override
public void clear() {
clearOnCommit = true;
entriesToAddOnCommit.clear();
}
//将当前队列待提交的数据提交到缓存中,并且重新设置标志,清空队列
public void commit() {
if (clearOnCommit) {
delegate.clear();
}
flushPendingEntries();
reset();
}

public void rollback() {
unlockMissedEntries();
reset();
}

private void reset() {
clearOnCommit = false;
entriesToAddOnCommit.clear();
entriesMissedInCache.clear();
}

private void flushPendingEntries() {
for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) {
delegate.putObject(entry.getKey(), entry.getValue());
}
//同时也将未命中的数据在缓存中设置为空
for (Object entry : entriesMissedInCache) {
if (!entriesToAddOnCommit.containsKey(entry)) {
delegate.putObject(entry, null);
}
}
}
//去掉缓存中未命中的数据
private void unlockMissedEntries() {
for (Object entry : entriesMissedInCache) {
try {
delegate.removeObject(entry);
} catch (Exception e) {
log.warn("Unexpected exception while notifiying a rollback to the cache adapter."
+ "Consider upgrading your cache adapter to the latest version. Cause: " + e);
}
}
}

}




BaseExecutor#query

@SuppressWarnings("unchecked")
@Override
public <E> List<E> 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());
//使用同一个sqlSession关闭的时候会调用Executor.close
if (closed) {
throw new ExecutorException("Executor was closed.");
}
//与之前不同的是这里清除的是一级缓存
//queryStack的作用是当多个查询使用的是同一个SqlSession即同一个Executor时,
//这些查询之间是并发进行的,如果后面的某个select语句的flushCache=true会导致其他语句的缓存被清除,即一个flushCache导致其他语句缓存失效,这是应该避免的,所以有且仅仅当当前flushCache=true的语句是当前session的第一个语句或者当前语句总是在当前session最先执行,即可保证其他缓存不被清除
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List<E> list;
try {
//每执行一次++1,可判断当前是否能进行缓存清除
queryStack++;
//同二级缓存只有在resultHandler为空的情况下一级缓存才保持有效
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
//如果list不为空处理callable语句
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
//从数据库获取
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
//最后执行
queryStack--;
}
//查询完成后执行延迟加载,如果是语句中包含嵌套语句,并且嵌套语句的值已经在一级缓存中,就调用当前Executor的deferLoad生成一个,DeferredLoad包含当前返回结果的MetaObject,objectFactory,resultExtractor等。这里执行load方法就从缓存中获取嵌套的语句值设置给自己,达到加快速度的目的,queryStack=0代表着当前查询结束
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
deferredLoads.clear();
//如果本地缓存scope 是语句级清除当前缓存
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
clearLocalCache();
}
}
return list;
}


SimpleExecutor#doQuery
BaseExecutor执行query真正调用的是SimpleExecutor的doQuery方法
  @Override
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.<E>query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}

Configuration#newStatementHandler 创建StatementHandler

  public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//RoutingStatementHandler是几种StatementHandler的封装

StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
statementHandler = (StatementHandler)
//前面执行了Executor的拦截器,这里执行的是StatementHandler的拦截器,即此处的拦截器被当做StatementHandler
interceptorChain.pluginAll(statementHandler);
return statementHandler;
}

SimpleExecutor#prepareStatement 创建预处理语句,设置参数
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
//获取连接
Connection connection = getConnection(statementLog);
//设置语句
stmt = handler.prepare(connection, transaction.getTimeout());
//设置参数
handler.parameterize(stmt);
return stmt;
}


BaseExecutor#getConnection
获取Connection对Connection进行动态代理,添加日志功能
 protected Connection getConnection(Log statementLog) throws SQLException {
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}


RoutingStatementHandler#prepare
调用被装饰的SatementHandler的prepare
 public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
return delegate.prepare(connection, transactionTimeout);
}


BaseStatementHandler#prepare
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
statement = instantiateStatement(connection);
setStatementTimeout(statement, transactionTimeout);
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#instantiateStatement

@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
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);
}
} else if (mappedStatement.getResultSetType() != null) {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
return connection.prepareStatement(sql);
}
}



//PreparedStatementHandler#parameterize
@Override
public void parameterize(Statement statement) throws SQLException {
//BaseStatementHanlder构造方法
// this.parameterHandler = configuration.newParameterHandler(mappedStatement,
//parameterObject, boundSql);

parameterHandler.setParameters((PreparedStatement) statement);
}

//DefaultParameterHandler#setParameters
/**
遍历parameterMappings,获取当前参数中的属性名称,如果boundsql有附加参数,第一优先级为附加参数,如果已经在Configuration中配置了自定义类型处理器,使用自定义类型处理器设置参数,否则使用MetaObject获取参数中的值,最后调用TypeHandler设置参数值,这里的BaseTypeHandler中setParameter调用子类的setNonNullParameter,至此SimpleExecutor的prepareStatement就执行完成了,SimpleExecutor的doQuery方法已经完成了StatementHandler的生成和Statement的生成,下一步就是执行带参数的Statement,
statement被传入StatementHandler(RoutingStatementHandler)的query继续向下委托


**/
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
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.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
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);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
} catch (SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}

PreparedStatementHandler#query

执行完语句,PreparedStatementHandler回调resultSetHandler的handleResultSets方法,resultSetHandler是在BaseHandler中的构造方法中进行初始化的
  this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);


@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值