mysql驱动版本变更导致查询数据结果一直是空

1 引言

最近接手了一个已离职同事的java项目,这个项目中原来使用了自己的mysql驱动版本,并未使用公司公共依赖中的版本号。我想为了统一版本号,就将当前项目中pom文件中mysql的版本号verson给去除了。没怎么自测,就直接发到测试环境了,结果没多久就有测试人员告诉了说,有接口报错。
其主逻辑sql如下

SELECT * FROM rule_category where `name`='企业资质' and parent_id=0;

后面发现不止这个接口查询结果为空,其他好几个接口的查询结果都未空。我用同样的sql语句在navicat中能查出结果,我开始怀疑我是不是连错数据库了,是不是连接到开发环境中的数据库。我使用Environment#getProperty("spring.datasource.url")获取到的数据库url可以确定是测试环境。后面进一步发现这些接口中都有中文查询条件,我开始怀疑是字符集的问题。回到刚才的数据库连接URL,其格式是jdbc:mysql://xxhost:3306/rule_engine?serverTimezone=GMT%2B8 ,这个URL明显没有指定字符集编码,我在这个url上加上characterEncoding=UTF8参数,本地重新启动项目,在swagger中调用接口,最终预期数据正常返回。
现在问题是解决了,大致应该是不同版本的数据库驱动其默认字符集编码不同。这个项目的原始数据库驱动版本是8.0.32 ,而我修改后继承了父依赖的版本号8.0.21

先看mysql-connector 8.0.32

com.mysql.cj.NativeCharsetSettings#NativeCharsetSettings 是mysql驱动 8.0.32 中的一个字符集配置相关的类,
在这里插入图片描述
上面的characterEncoding字段的description的大致意思是在未主动配字符集编码时,8.0.25及以下版本的数据库驱动会使用mysql服务器的默认编码,而在8.0.26及以上版本的数据库驱动会使用utf8mb4

8.0.32版的mysql驱动在建立socket连接之前,会调用com.mysql.cj.NativeCharsetSettings#configurePreHandshake方法
在这里插入图片描述
sessionCollationIndex为null,先给它赋值为utf8mb4_0900_ai_ci字符集对应的index,在然后根据数据库服务器版本号重新进一步赋值,我们公司数据库的版本5.7.39,此版本号小于下图中的8.0.1会被赋值为 utf8mb4_general_ci对应的index。所以可以看出8.0.23版本的mysql驱动的默认字符集编码是utfmb8
在这里插入图片描述

再看下面的connectionCollation的说明,这个属性是字符排序规则,这里还提到了字符编码。如果connectionCollation是latin1_swedish_ci,那么mysql的字符集就是latin1 ,而映射到java语言就是windows-1252字符集,如果characterEncoding没有被设置,那么就会使用windows-1252字符集。这里最后几句话再次说明了:characterEncoding没有被主动设置时,在8.0.25以下版本,使用数据库server端的默认字符编码,而在8.0.26及以上版本,直接使用utf8mb4编码。
在这里插入图片描述

再看mysql-connector 8.0.21

类似地此版本的驱动在建立正式的socket连接之前,会调用com.mysql.cj.NativeCharsetSettings#configurePreHandshake方法
在这里插入图片描述
configurePreHandshake又会调用 readServerCapabilities方法,readServerCapabilities方法就是解析mysql server返回的第一数据报文,这个数据报文中包含了mysql server的通信协议版本、数据库版、默认字符集等信息。readServerCapabilities方法
的核心的逻辑在serverCapabilities.setInitialHandshakePacket(buf)这行代码
在这里插入图片描述
在这里插入图片描述
从下图可以看出 mysql server的默认字符集编码是latin1,对应的java字符集是windows-1252
在这里插入图片描述
为了验证mysql server的默认字符集是否是latin1, 可以在navicat执行一个这个SQL脚本

show VARIABLES like '%set_database';

下图显示其字符集编码果然是latin1
在这里插入图片描述
而数据库的表字段rule_category.name是utf8mb4,在8.0.21版本的驱动使用mysql server默认的latin1编码去查询utf8mb4编码的 name字段,当然会导致条件不匹配,查询结果为空
在这里插入图片描述

  • 33
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值