編碼鏈路任一環節不一致即導致亂碼:
Java 字串(UTF-16)
→ [JDBC 驅動編碼] →
網路傳輸位元組流
→ [MySQL 連接編碼 character_set_connection] →
MySQL 內部操作
→ [資料表/欄位編碼 character_set_column] →
磁碟儲存
常見斷點:
-- 1. 資料庫/表/欄位全改 UTF-8 (utf8mb4 支援 Emoji)
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 或建表時指定
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 2. 連接串:明確指定 UTF-8,不依賴預設
jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
-- 資料庫/表/欄位均為 GBK
CREATE DATABASE mydb CHARACTER SET gbk COLLATE gbk_chinese_ci;
-- 連接串對應 GBK
jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=gbk&serverTimezone=Asia/Shanghai
SHOW VARIABLES LIKE 'character_set_%';
SHOW CREATE TABLE user;
關鍵變數應顯示:
| 錯誤做法 | 正確做法 |
|---|---|
| 連接串用 `UTF-8`(大寫/中劃線) | MySQL 識別名為 `utf8` 或 `utf8mb4`(無中劃線) |
| 只改連接串,不改資料庫/表編碼 | 全鏈路統一,缺一不可 |
| 用 `Statement` 拼接 SQL 字串 | 用 `PreparedStatement` 參數化,避免編碼/注入雙重風險 |
| MySQL 5.7 用 `utf8` 存 Emoji | 必須用 `utf8mb4` |
| 驅動版本過舊 (5.1.30 以前) | 升級至 8.0.x (支援 MySQL 5.7/8.0) |
中文亂碼本質是編碼鏈路不一致。現代專案全鏈路統一 UTF-8 (utf8mb4) 是最省心、最通用、最面向未來的方案。老系統若無法遷移,則嚴格對齊 GBK 全鏈路。務必使用 `PreparedStatement` 參數化查詢,杜絕拼接 SQL 帶來的編碼與安全雙重隱患。