侧边栏壁纸
博主头像
牧云

怀璧慎显,博识谨言。

  • 累计撰写 207 篇文章
  • 累计创建 20 个标签
  • 累计收到 8 条评论

目 录CONTENT

文章目录

JDBC 中的 characterEncoding 与 connectionCollation

秋之牧云
2026-06-17 / 0 评论 / 0 点赞 / 4 阅读 / 0 字

在配置 MySQL JDBC 连接字符串时,你是否也曾对着下面这串参数发呆?

jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&connectionCollation=utf8mb4_general_ci

characterEncoding 是什么?connectionCollation 又是什么?为什么有时候只配一个就行,有时候两个都配却还乱码?

今天,我们就从底层原理最佳实践,彻底拆解这两个容易混淆的参数,帮你终结“中文乱码”噩梦。


1. 核心概念:它们到底管什么?

虽然它们都跟“字符”有关,但负责的环节完全不同。

🔹 characterEncoding:客户端的“翻译官”

  • 所属层级JDBC 驱动层(Client Side)
  • 作用:告诉 Java 应用程序(JDBC Driver),在将 Java String(UTF-16 编码)发送给 MySQL 服务器之前,应该转换成什么字节序列。
  • 常见值UTF-8, GBK, ISO-8859-1
  • 本质:它解决的是 “Java 内存 -> 网络传输” 这一段的编码问题。

🔹 connectionCollation:服务端的“排序规则”

  • 所属层级MySQL 服务器层(Server Side)
  • 作用:告诉 MySQL 服务器,当前连接会话默认使用哪种字符集(Character Set)排序规则(Collation)
  • 常见值utf8mb4_general_ci, utf8mb4_unicode_ci, utf8mb4_0900_ai_ci
  • 本质:它解决的是 “数据存储、比较、排序” 的逻辑问题。
    • 注意:指定 Collation 的同时,隐含指定了 Character Set。例如 utf8mb4_unicode_ci 隐含字符集为 utf8mb4

2. 工作流程图解

当你的 Java 代码执行 statement.setString(1, "你好") 时,数据经历了以下旅程:

  1. 步骤 1:JDBC 驱动查看 characterEncoding 参数。如果设为 UTF-8,驱动会将 "你好" 编码为 UTF-8 字节流。
  2. 步骤 2:字节流通过 TCP 发送给 MySQL。
  3. 步骤 3:MySQL 接收字节流。此时,MySQL 查看当前会话的 connectionCollation
    • 如果 Collation 是 utf8mb4_...,MySQL 知道这些字节是 utf8mb4 编码的,于是正确解码并存储。
    • 如果 Collation 是 latin1_...,MySQL 会误以为这是拉丁文,导致乱码

💡 关键点:只有当 客户端发送的编码服务端理解的编码 一致时,数据才能正确存储。


3. 常见误区与坑

❌ 误区一:characterEncoding=utf8mb4 是合法的?

错!

  • characterEncoding 是 Java 标准的字符集名称。Java 中只有 UTF-8,没有 utf8mb4
  • 如果你在 JDBC URL 中写 characterEncoding=utf8mb4,较新的驱动可能会报错,或者静默失败回退到平台默认编码(如 GBK),导致乱码。
  • 正确写法characterEncoding=UTF-8

❌ 误区二:只要设了 connectionCollation,就不需要 characterEncoding

大部分情况下是对的,但有前提。

  • 在现代 JDBC 驱动(8.x+)中,如果你指定了 connectionCollation=utf8mb4_unicode_ci,驱动足够智能,会自动将客户端编码设置为 UTF-8。
  • 但在旧版驱动(5.1.x)或某些特殊环境下,显式指定 characterEncoding=UTF-8 是一种双重保险

❌ 误区三:utf8utf8mb4 是一回事?

在 MySQL 中,绝对不是!

  • MySQL 的 utf8 只支持最多 3 字节字符(不支持 Emoji 🤔)。
  • MySQL 的 utf8mb4 支持 4 字节字符(完整 Unicode,支持 Emoji)。
  • JDBC 层面:Java 的 UTF-8 编码可以表示所有 Unicode 字符。
  • 结论:JDBC 传 UTF-8 没问题,但 MySQL 端必须用 utf8mb4 系列 Collation 才能存下 Emoji。

4. 最佳实践推荐

根据你的 MySQL 版本和驱动版本,选择以下一种配置方案。

✅ 方案 A:现代标准推荐(MySQL 8.0 + Connector/J 8.x)

这是最简洁、最推荐的写法。利用 connectionCollation 统一控制字符集和排序。

jdbc.url=jdbc:mysql://host:3306/db?
  useSSL=false&
  serverTimezone=Asia/Shanghai&
  connectionCollation=utf8mb4_0900_ai_ci

注:utf8mb4_0900_ai_ci_ 是 MySQL 8.0 的默认排序规则,性能更好,排序更准确。如果是 5.7,请用 utf8mb4_unicode_ci。_

✅ 方案 B:保守兼容写法(MySQL 5.7 / 老项目迁移)

如果你担心旧驱动的行为不一致,或者团队规范要求显式声明,可以使用“双保险”模式。

jdbc.url=jdbc:mysql://host:3306/db?
  useUnicode=true&
  characterEncoding=UTF-8&
  connectionCollation=utf8mb4_unicode_ci&
  serverTimezone=Asia/Shanghai

注意:这里 characterEncoding 必须是大写的 UTF-8 或标准的 utf-8,绝不能写 utf8mb4


5. 如何验证配置是否生效?

连接数据库后,执行以下 SQL 检查当前会话状态:

SHOW VARIABLES LIKE 'character_set_client';
SHOW VARIABLES LIKE 'character_set_connection';
SHOW VARIABLES LIKE 'collation_connection';

期望结果:

  • character_set_client: utf8mb4
  • character_set_connection: utf8mb4
  • collation_connection: utf8mb4_unicode_ci (或你指定的值)

如果 clientconnection 显示为 latin1gbk,说明配置未生效,请检查 JDBC URL 拼写或驱动版本。


6. 总结

参数建议值作用域是否必填
characterEncodingUTF-8JDBC 驱动客户端可选(新版驱动可省略)
connectionCollationutf8mb4_unicode_ciutf8mb4_0900_ai_ciMySQL 服务端会话强烈推荐

一句话建议:
优先配置 connectionCollationutf8mb4_unicode_ci(或 8.0 的 0900_ai_ci),它能同时搞定字符集和排序规则。除非你在维护十年前的老系统,否则无需过度纠结 characterEncoding,保持默认或显式指定 UTF-8 即可。


希望这篇文章能帮你理清思路!如果你的项目中还在用 utf8_general_ci,是时候考虑升级啦!🚀

0

评论区