背景
使用 TDengine
集成 MyBatistPlus
后,对我自己建的数据表进行分页查询时闪退,同时有条信息: Process finished with exit code -1073741819 (0xC0000005)
。
我们知道, MyBatistPlus
的分页查询时先查询记录的总数,再进行分页条件查询,仔细观察 MyBatistPlus
控制台日志生成的SQL语句: SELECT COUNT(1) FROM ( SELECT ts, voltage, current, temperature, sn, city, groupid FROM power ) TOTAL;
,直接将这条SQL语句放在 taos
的客户端命令行执行是正确的(当然,需要先切换至对应的数据库: use ok;
)。
分析问题
- 难道是环境问题?
统一了 SpringBoot
、 MyBatisPlus
、 taos-jdbcdriver
的版本,以及JDK、编译器的版本,甚至将官方SpringBoot与 MyBatistPlus
集成的例子放进同一个项目, Temperature
可正常分页查询,可一到我的 Power
就不对了;所以是我的表有问题。
- 难道是因为数据量太大?
自己建的表超过1亿条数据, 官方示例中的 Temperature
是用来测试的,里面总共就几张子表,数据量也是个位数,可我试了官方的 meters
表, 100000000
条数据,分页查询正常呀;所以是我的表有问题。
- 难道是我建的表有问题?
是我建表方式有问题?可对照官网说明仔细检查了十来八遍,没发现建库、建表语句有啥问题。而且 TDengine
官方文档中也是有这样的示例的:
Note: 建库建表语句如下(以下是经过简化后的,仅写入两条数据,说明问题即可):
create database if not exists ok; create stable if not exists ok.power(ts timestamp, voltage int, current float, temperature float) tags(sn int, city nchar(64), groupid int); create table if not exists ok.device1 using ok.power tags(1, "太原", 1); create table if not exists ok.device2 using ok.power tags(2, "西安", 2); insert into ok.device1 values("2021-09-04 21:03:38.734", 1, 1.0, 1.0); insert into ok.device2 values("2021-09-04 21:03:40.734", 2, 2.0, 2.0);
见鬼,我竟然开始怀疑人生了。
我决定跟踪下 MyBatisPlus
分页查询拦截器的源码,到底为啥我建的表会导致查询数据总量的SQL与别人的不一样。
-- 通过 `MyBatisPlus` 分页查询官方meter表生成的count查询语句 SELECT COUNT(1) FROM meters -- 通过 `MyBatisPlus` 分页查询官方我建的表生成的count查询语句 SELECT COUNT(1) FROM ( SELECT ts, voltage, current, temperature, sn, city, groupid FROM power ) TOTAL
源码调试
从配置的分页拦截器位置开始,一步步调试。
net.sf.jsqlparser.parser. ParseException: Encountered unexpected token: "current"
当看到这个信息时,瞬间炸裂,一下子就知道错哪里了, current
有 现在的;电流
的意思,当年也是虐过四六级的人。。这跟英语好不好没啥关系,而是跟编码基础与习惯、细心程度密切相关。这种细节错误很容易就被忽略,导致南辕北辙,耗费掉大半天时光。其实跟踪起来倒也不太难,只是刚开始没往这个方向思考。
JsqlParserCountOptimize里的parser方法,try中的第一行代码直接到了catch块里,显然,这第一行抛异常了。。
而且, IDEA
的高亮语法显示其实早已经标明了 current
是个关键字/保留字,只是,一开始的注意力根本没放在这里。
解决问题
显然,换个名字吧,字段名不能使用 mysql
的关键字以及保留字(虽然在 TDengine
中一切正常),一般遇到 order
这种关键字出现在表名、字段名中时,我们会用反引号括起来,但是这里通过分页插件的查询代码显然没帮我们做这件事。
这个问题的根本是我们不应该使用保留字 current
作为字段名,但引起麻烦的是这个分页插件并没有向我们显式的报错,而是仅展示了一段莫名其妙的信息: Process finished with exit code -1073741819 (0xC0000005)
(网上查了下这个报错,很多说是跟金山词霸有关系,这个。。真心没用过)。
另外,如果使用 MyBatistPlus
的 selectList
方法,则正常执行。。 sigh
总结
current
作为字段名在 TDengine
中正常,在 MySQL
中用反引号括起来也正常;然而,当 TDengine
集成 MyBatistPlus
后,分页查询时,问题出现了。。在 TDengine
里用的好好的字段名,却被 MySQL
狠狠上了一课。