关于Mybatis-plus集成ClickHouse导致的Bug
以下代码均为demo代码,不是实际工作代码
问题描述:
使用Clickhouse的union distinct进行查询时,返回的结果都为null
现象如下截图所示:
这里可以看出是有记录,但是为null
初步解决思路
1、SQL问题导致
第一想法是sql问题,但是马上就排除了这个原因,因为这里显示的是有记录的,只是没有获取到字段值而已。
并且将控制台打印出来的sql放到dbeaver中执行了一下,显示的结果是符合预期的,所以排除是SQL导致的问题
2、字段名称不一致导致
如果字段名称不一致的话肯定会导致这个问题,但是这个原因也马上被排除,因为在demo代码中我一开始就将数据
库的字段和实体字段名设置为一致的,所以也不是这个原因。
3、mybatis的字段下划线、驼峰转换导致的字段不一致导致
在工作代码中实体字段和数据库字段都是下划线格式(c_username),所以当看到这里时觉得应该就是这个原因,因为mybatis是默认开始下划线转驼峰的,所以将实体字段全部改为驼峰格式,但是事实证明也不是这个原因。。。
4、字段类型不一致导致
最后想到可能是因为数据库的字段类型和实体类型不一致导致的类型转换失败,所以全部为null???但是经过检查类型是相符合的,所以也是这个原因。。。
经过上述的基本排查,没有找到真正的原因,所以感觉事情不是那么简单,所以继续挖掘原因
观察现象
虽然自己定义的实体字段无法获取到相应的值,但是这里确实显示有记录,所以将实体换位JSONObject或者map来看看返回的数据到底是什么样的
看到这个返回结果,让我大为感叹,直呼卧槽!! 这TN什么鬼???
当看到这里的时候我已经是蒙圈了,原本的字段值怎么变成了字段名?? 并且上网搜索也没有搜到相应的答案(可能是我的打开方式不对)
但是仔细一想,平时自己写的sql也并没有这种问题,所以**怀疑是不是对结果进行union操作导致的问题**
再次尝试解决思路
1、两表union导致的问题
将两表union查询换为了单表查询后果然ok了
但是我必须得进行union操作,所以只能将问题集中在union上面,看看如何解决
2、union distinct导致的问题
现在确定是因为union操作导致的问题,所以查阅ClickHouse文档 union操作有两种方式:
-
UNION ALL
-
UNION DISTINCT
顾名思义,以上两种方式一种会去重(DISTINCT)一种不会(ALL),现在使用的是UNION DISTINCT,所以尝试使用不去重的方式来试试会不会有问题
原因不必多言,就是因为**union distinct**导致的
解决问题
现在bug原因指向了UNION DISTINCT操作,为了了解这两种方式的更多区别,再次查阅ClickHouse的官方文档:https://clickhouse.com/docs/en/sql-reference/statements/select/union/
其实官方文档也没有基于很多的解释,因为单从sql执行结果上来看是没有问题的,所以我猜测这是因为Mybatis与ClickHouse的适配问题,所以按照文档上给出的指示,进行的sql的改造
- 将原来的union distinct 改为 union all
- 将原来的sql作为一个子查询,并在外层查询的select处进行去重操作
这次问题确实得到了解决
虽然问题解决了,但是总感觉莫名其妙,所以准备深入源码寻找导致问题的原因所在
一探究竟
将断点达到处理ResultSet的地方org.apache.ibatis.executor.resultset.DefaultResultSetHandler#getFirstResultSet
发现这里在解析column的时候将第一行数据的值作为了name,这不很扯淡吗??? 这时突然想起刚才在看ClickHouse文档的时候好像看到过类似的说明,这个时候再次回到ClickHouse的官当文档
在文档中有这么一句话,好像跟当前的这个问题有关,因为最后所说的这个现象正是现在所看到的,但是他所说的前提结果列与其索引匹配。。。。。 但是转头一想,sql在dbeaver中的执行结果是正常的,最终将问题指向了clickhouse的driver,会不会这个问题在最新的版本已经修复了呢???
然后将版本升到最新版发现还是一个样。。。。至此,我已别无他法只能选择放弃,改用子查询的方式来执行原sql
最后
贴出执行UNION ALL 和 UNION DISTINCT在解析column name处的区别,代码位于ru.yandex.clickhouse.response.ClickHouseResultSet#ClickHouseResultSet
-
UNION ALL
-
UNION DISTINCT