【问题定位】通过看Mybatis源码解决系统问题

开发需求好好的,运维同事突然发现了一个问题,某个任务的详情页面加载不出来。看日志,系统在进行查询操作的时候抛出空指针异常。感觉是Mybatis内部异常,所以就跟踪源码看下Mybatis运行到哪一步报错的。

DefaultSqlSession#selectOne(java.lang.String, java.lang.Object),空指针异常的地方是从DefaultSqlSession报出来的,由于查询结果返回null,导致调用size方法报错。

  @Overridepublic <T> T selectOne(String statement, Object parameter) {// Popular vote was to return null on 0 results and throw exception on too many.List<T> 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;}}

BaseExecutor#query()BaseExecutor的query方法是Mybatis执行查询sql的必经之路,这边有一级缓存和二级缓存的知识点。

  @Overridepublic <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());if (closed) {throw new ExecutorException("Executor was closed.");}if (queryStack == 0 && ms.isFlushCacheRequired()) {clearLocalCache();}List<E> list;try {queryStack++;list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;if (list != null) {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 #601deferredLoads.clear();if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {// issue #482clearLocalCache();}}return list;}

SimpleExecutor#doQuery,这个方法有两个重要的方法调用,prepareStatement()主要是给预编译的sql设置参数,handler.query(stmt, resultHandler);是获取数据,并进行对象封装。

  @Overridepublic <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);}}

DefaultResultSetHandler#handleResultSets,将查询出来的数据集合挨个解析。

  @Overridepublic List<Object> handleResultSets(Statement stmt) throws SQLException {ErrorContext.instance().activity("handling results").object(mappedStatement.getId());final List<Object> multipleResults = new ArrayList<>();int resultSetCount = 0;ResultSetWrapper rsw = getFirstResultSet(stmt);List<ResultMap> resultMaps = mappedStatement.getResultMaps();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.getResultSets();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);}

DefaultResultSetHandler#applyPropertyMappings,该方法是将挨个数据库中的列数据映射到属性中。当系统遍历到日期字段,end的时候,该方法报错,跳出。

  private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)throws SQLException {final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);boolean foundValues = false;final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();for (ResultMapping propertyMapping : propertyMappings) {String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);if (propertyMapping.getNestedResultMapId() != null) {// the user added a column attribute to a nested result map, ignore itcolumn = null;}if (propertyMapping.isCompositeResult()|| (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))|| propertyMapping.getResultSet() != null) {Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);// issue #541 make property optionalfinal String property = propertyMapping.getProperty();if (property == null) {continue;} else if (value == DEFERRED) {foundValues = true;continue;}if (value != null) {foundValues = true;}if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {// gcode issue #377, call setter on nulls (value is not 'found')metaObject.setValue(property, value);}}}return foundValues;}

因此发现该行数据的end字段有问题,用Datagrip查询,该字段的数据是2023-11-31 23:59:59,而2023年11月份是没有31号的,所以mybatis赋值会报错。mysql允许非法的日期格式插入,但是mybatis对于这非法的数据处理是处理不了的。

总结:

  1. mybatis查询的核心流程就是解析sql,执行sql,封装对象。空指针异常不是对象为空,可能是mybatis在数据处理的过程中有异常。
  2. 注意数据插入的合法性。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/159578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年亚太杯数学建模思路 - 案例:粒子群算法

文章目录 1 什么是粒子群算法&#xff1f;2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法&#xff1f; 粒子群算法&#xff08;Pa…

PostgreSQL导出表结构带注释

我们在平时开发过程中&#xff0c;经常会在字段的注释中&#xff0c;加上中文&#xff0c;解释字段的相关含义&#xff0c;也可以避免时间太久忘记这个字段代表什么&#xff0c;毕竟英文水平不好。我们可能要经常整理数据库表结构&#xff0c;提供他人去收集数据&#xff0c;但…

SQLite3 数据库学习(四):Qt 数据库基础操作

参考引用 SQLite 权威指南&#xff08;第二版&#xff09;SQLite3 入门 1. 创建连接执行 sql 语句 在 Qt 中使用数据库要在工程文件中添加QT sql1.1 main.cpp #include "createsqlapp.h" #include <QApplication> #include <QSqlDatabase> #include &l…

香港高端人才通行证计划申请(包括条件)你需要知道的这些真相!

香港高端人才通行证计划申请&#xff08;包括条件&#xff09;你需要知道的这些真相&#xff01; 香港高才通计划从刚推出就带着“光速获批“的光环&#xff0c;吸引了大批高学历和高收入人士&#xff0c;后续也因它申请要求简单、明确&#xff0c;获批率高等优势&#xff0c;火…

主机dbeaver访问gitlab容器中的pg

映射5432端口- 5431:5432或者从docker客户端查看 version: 3.6 services:web:image: gitlab/gitlab-ce:latestrestart: alwayshostname: localhostenvironment:GITLAB_OMNIBUS_CONFIG: |external_url http://localhost:8929gitlab_rails[gitlab_shell_ssh_port] 2224ports:- …

文心一言 VS 讯飞星火 VS chatgpt (140)-- 算法导论11.4 5题

五、用go语言&#xff0c;考虑一个装载因子为a的开放寻址散列表。找出一个非零的a值&#xff0c;使得一次不成功查找的探查期望数是一次成功查找的探查期望数的 2 倍。这两个探查期望数可以使用定理11.6 和定理 11.8 中给定的上界。 文心一言&#xff0c;代码正常运行&#xf…

springboot宠物领养系统-计算机毕设 附源码 44261

springboot宠物领养系统 摘 要 网络发布信息有其突出的优点&#xff0c;即信息量大&#xff0c;资源丰富&#xff0c;更新速度快等&#xff0c;很符合人们希望以捷、便利的方式获得最多最有效信息的要求。本系统就是一个网上宠物领养系统&#xff0c;为宠物爱好者提供一个信息…

pyqt5 窗口调用网页高德地图kpi,进行实时地图导航

作为主项目功能的一部分&#xff0c;这部分我想单独记录下来 一&#xff0c;注册高德kpi【进行实名认证】 高德开放平台 | 高德地图API (amap.com) 二&#xff0c;申请Key 三&#xff0c;进入路径规划-API文档-开发指南-Web服务 API|高德地图API (amap.com) 找到你需要的路径…

【必读】从零开始,一步步教你安装nginx,搭建个人博客网站!

nginx搭建个人网站 Nginx是一款轻量级Web服务器、反向代理服务器以及电子邮件代理服务器&#xff0c;并且具有高并发连接处理能力和低内存消耗的特点。它也可以用于负载均衡和缓存控制等功能。 功能&#xff1a; 静态网站服务器&#xff1a;Nginx可以用来作为静态网站服务器&am…

员工微信私下收红包,企业如何加强监管

随着智能手机的普及和社交软件的兴起&#xff0c;越来越多的企业和员工开始使用微信等社交应用程序进行日常工作交流和业务协作。然而&#xff0c;与此同时&#xff0c;一些行业的员工在微信上私下收取红包的问题也日益严重&#xff0c;这不仅违反了公司的规定&#xff0c;也损…

Kubernetes+Gitlab+Jenkins+ArgoCD多集群部署

KubernetesGitlabJenkinsArgoCD多集群部署 文章目录 KubernetesGitlabJenkinsArgoCD多集群部署1. KubernetesGitlabJenkinsArgoCD多集群部署2. 添加WebHooks自动触发3. Jenkins-构建-执行Shell4. 制作镜像及修改Yaml文件4.1 Dockerfile4.2 Build-Shell 5.自动部署Demo测试5.1 推…

JSP EL表达式基本使用

今天我们来说EL表达式 这在整个jsp中都是非常重要的一章 因为 如果我们用 <%属性%> 属性为空时 直接就是个 null 这个肯定是不能让用户看到的东西 所以 我们就需要EL表达式 例如 我们jsp代码编写如下 <% page contentType"text/html; charsetUTF-8" page…

React函数组件渲染两次

渲染两次是因为react默认开启了严格模式 React.StrictMode标签作用&#xff1a; 1、识别不安全的生命周期 2、关于使用过时字符串 ref API 的警告 3、关于使用废弃的 findDOMNode 方法的警告 4、检测意外的副作用 5、检测过时的 context API 注释掉React.StrictMode即为关闭严…

【Windows 常用工具系列 12 -- win11怎么设置不睡眠熄屏 |win11设置永不睡眠的方法】

文章目录 win11 怎么设置不睡眠熄屏 使用笔记本电脑的时候&#xff0c;如果离开电脑时间稍微长一点就会发现息屏了&#xff0c;下面介绍 设置 Win11 永不睡眠息屏的方法&#xff0c;有需要的朋友们快来看看以下详细的教程。 win11 怎么设置不睡眠熄屏 在电脑桌面上&#xff0c…

微信怎么设置自动回复?

自动回复的用处 微信自动回复可以提高沟通效率。当你无法立即回复消息时&#xff0c;设置自动回复可以让对方知道你的情况&#xff0c;并且不会因为长时间没有回复而产生误解或不满。 微信自动回复可以节省时间和精力。如果你经常收到类似的询问或回复&#xff0c;通过设置自动…

STM32CubeMX学习笔记(2)--DSP库的使用

1.DSP库简介 STM32的DSP库是为了支持数字信号处理应用而设计的&#xff0c;它包含了一系列优化的数学函数和算法&#xff0c;能够在STM32微控制器上高效地执行数字信号处理任务。 DSP库通常包括以下主要特性&#xff1a; 1.数学函数库&#xff1a; 包括各种基本的数学运算函数…

Python语言:猜数字游戏案例讲解

猜数字游戏题目要求如下&#xff1a;该程序随机生成一个1到100之间的整数&#xff0c;然后要求玩家在有限的次数内猜出这个数字。如果玩家猜对了&#xff0c;游戏结束并显示成功信息&#xff1b;如果玩家猜错了&#xff0c;程序会提示玩家猜的数字是偏大还是偏小&#xff0c;并…

O2OA(翱途)开发平台 V8.2已发布,更安全、更高效、更开放

尊敬的 O2OA (翱途) 平台合作伙伴、用户以及亲爱的开发小伙伴们&#xff0c;V8.2 版本已正式发布&#xff0c;大家可以去官网上下载最新版本。 上次 8.1 的发布是在 9 月 1 日&#xff0c;又过去两个多月&#xff0c;O2OA 研发团队始终踏踏实实地做好产品的研发及优化工作&…

③【List】Redis常用数据类型: List [使用手册]

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Redis List ③Redis List 操作命令汇总1. lpus…

6 Redis的慢查询配置

1、redis的命令执行流程 redis的慢查询只针对步骤3 默认情况下&#xff0c;慢查询的阈值是10ms 在配置文件中进行配置 //这个参数的单位为微秒 //如果将这个值设置为负数&#xff0c;则会禁用慢日志功能 //如果将其设置为0&#xff0c;则会强制记录每个命令 slowlog-log-slow…