one方法报错 select_mybatis中selectOne方法分析
0首先获取sqlSession,大致流程如下
SqlSessionFactoryBuilder->SqlSessionFactory
SimpleExecutor .
CachingExecutor
SqlSession session=sqlSessionFactory.openSession();
DefaultSqlSession类
public T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
//转而去调用selectList,很简单的,如果得到0条则返回null,得到1条则返回1条,得到多条报TooManyResultsException错
// 特别需要主要的是当没有查询到结果的时候就会返回null。因此一般建议在mapper中编写resultType的时候使用包装类型
//而不是基本类型,比如推荐使用Integer而不是int。这样就可以避免NPE
List list = this.selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
//核心selectList
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();
}
}
CachingExecutor类
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 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);
}
BaseExecutor类
@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;
}
//从数据库查
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;
}
@Override
public List handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
final List multipleResults = new ArrayList();
int resultSetCount = 0;
ResultSetWrapper rsw = getFirstResultSet(stmt);
List resultMaps = mappedStatement.getResultMaps();
//一般resultMaps里只有一个元素
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
String[] resultSets = mappedStatement.getResulSets();
if (resultSets != null) {
while (rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
handleResultSet(rsw, resultMap, null, parentMapping);
}
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
}
return collapseSingleResultList(multipleResults);
}
one方法报错 select_mybatis中selectOne方法分析相关推荐
- java中write方法报错_Java中管道报错:Write end dead
今天看了下关于管道的通信,Java中的管道只能在同一进程的不同线程间通信.今天测试两个线程进行通信发现报错.下面是我测试的代码. package com.wpl.testIO; import java ...
- python3中input()方法报错traceback变量未定义的解决方法
python3中input()方法报错traceback变量未定义的解决方法 参考文章: (1)python3中input()方法报错traceback变量未定义的解决方法 (2)https://ww ...
- vue父组件调用子组件方法报错的解决方法
vue父组件调用子组件方法报错 在父组件定义了一个tab标签页,每一个标签页下面都调用不同的组件,如下图所示: 子组件中定义的方法: setup() {const getList = () => ...
- Python调用seek(pos,mode)方法报错Can‘t do nonzero cur-relative seeks
在Python中IO操作调用seek(pos,mode)方法时,出现异常错误:OSError:Can't do nonzero cur-relative seeks其示例代码如下: from io i ...
- 基于adversarial-robustness-toolbox(ART)包进行AI对抗攻击ZOO攻击方法报错
基于adversarial-robustness-toolbox(ART)包进行AI对抗攻击ZOO攻击方法报错 环境 问题分析 问题解决 ZooAttack类使用扩展 环境 ART版本:1.14.0 ...
- getSupportFragmentManager().beginTransaction().add方法报错
图中红线报错时,发现明明一样但是无论如何改都会报错,这时候就要注意Fragment文件的extends导入的方法,它可能是导入的包不对 如图所示,Fragment有两个包,如果导入的是Android. ...
- java 实现接口后重写方法报错
java 实现接口后重写方法报错 java 实现接口后重写方法报错 The method contextDestroyed(ServletContextEvent) of type InitListe ...
- uEditor setContent方法报错Uncaught TypeError: Cannot read property ‘innerHTML‘ of undefined
uEditor setContent方法报错Uncaught TypeError: Cannot read property 'innerHTML' of undefined 报错信息 解决方法 报错 ...
- 快速解决Android studio native 方法报错
反编译一个游戏项目,发现native方法报错.如图: 项目是通过加载动态链接库so,没有jni的源码,导致native方法有红色波浪线,我们可以关闭android studio的jni支持. 点击An ...
最新文章
- pythongui登录界面密码显示_python的GUI之一个简单的登录界面
- ERP与GMP结合在药类企业实施及应用
- GitLab 8.3.3 发布 开源代码管理
- css那些事儿4 背景图像
- SkyEye——汽车电子系统仿真测试工具
- WGZX:javaScript 学习心得--1
- 网站登录页面php代码,一个简单的网页密码登陆php代码
- java20 创建服务器:ServerSocket
- android菜单详解四:子菜单
- I00028 整数逆序
- scanf 与 scanf_s
- Java(面向对象OOP)
- GIS相关网站、社区、论坛收藏
- M/M/m排队模型 (单队列多服务台并联服务模型)数学建模: 基于生灭过程的理论计算和基于事件推进的Matlab模拟仿真思路
- vue 创建项目使用npm还是yarn
- 形式验证——学习笔记
- oracle10安装完成之后测试,RHEL4U4和RHEL5安装oracle10g(测试过绝对可以成功)
- DuckDuckGo将与整合Apple Maps有更丰富的地图信息及隐私
- 云服务器微信faq,微信公众平台常见问题FAQ
- 超好的赚钱方法 目前广告点击报酬最高的
热门文章
- windows强制安装IE浏览器
- 爬虫Scrapy框架学习(三)-爬取苏宁图书信息案例
- 【35. 多重背包】
- SplunkEnterprise日志服务程序/SplunkForward通用转发器部署客户端
- MySQL 联级删除(on delete cascade)应用
- Linux下C编程入门(1)
- Crescendo:适用于macOS的实时事件查看器(2020)
- 微信远程代码执行漏洞(最新版本利用)-亲测已上线
- Python掘金3量化交易代码:判断当前持仓,如果是今天买的不能卖
- C#字符串- string.Format格式化