首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

Java + MySQL 中文亂碼徹底解決:字符集鏈路分析、連接參數配置與最佳實踐

     編輯:MySQL 綜合教學

亂碼根因:字符集鏈路不一致

MySQL 預設 latin1 (ISO-8859-1),Java 內部用 UTF-16,若連接層未正確聲明字符集,插入時「UTF-16 → latin1」截斷多字節字符,查詢時「latin1 → UTF-16」產生錯誤映射,形成亂碼。

字符集傳輸鏈路圖解


Java String (UTF-16) 
    ↓ JDBC Driver 轉換 (connectionEncoding)
網絡傳輸 (character_set_client)
    ↓ MySQL Server 轉換
存儲 (character_set_column / table / database)
    ↓ 讀取時反向轉換
結果集 (character_set_results)
    ↓ JDBC Driver 轉換
Java String (UTF-16)

方案一:連接 URL 參數配置 (推薦、零代碼改動)

jdbc:mysql://localhost:3306/dbname?
    useUnicode=true&
    characterEncoding=utf8mb4&
    serverTimezone=Asia/Shanghai&
    useSSL=false&
    allowPublicKeyRetrieval=true
  • useUnicode=true:啟用字符集轉換
  • characterEncoding=utf8mb4:指定傳輸編碼 (需 MySQL 5.5.3+)
  • serverTimezone:避免時區警告

方案二:MySQL 服務端配置 /etc/my.cnf (治本)

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4'  -- 非超級用戶自動生效

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

重啟後,新建表/庫自動繼承 utf8mb4,存量表需 ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4;

方案三:代碼層手動轉碼 (無法改配置時的備選)

插入數據:Java UTF-16 → ISO-8859-1 → 傳給 MySQL

String str = "中文";
// 關鍵:先獲取 UTF-8 字節,再按 ISO-8859-1 重構字符串
// 相當於告訴驅動:「這字符串已是 latin1 編碼」
str = new String(str.getBytes("UTF-8"), "ISO-8859-1");  

String sql = "INSERT INTO tb (col) VALUES (?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, str);
ps.executeUpdate();

讀取數據:MySQL latin1 → Java UTF-16

String str = rs.getString(1);
// 關鍵:按 ISO-8859-1 取字節,再按 UTF-8 解碼還原
str = new String(str.getBytes("ISO-8859-1"), "UTF-8");
// 或指定目標編碼 (如 GBK)
str = new String(str.getBytes("ISO-8859-1"), "GBK");

原理: 驅動按 characterEncoding 解碼網絡字節。若連接參數未生效 (如舊版驅動、連接池缓存),手動構造「偽 latin1 字符串」欺騙驅動按 latin1 發送,MySQL 再按列字符集 (utf8mb4) 正確存儲。

驗證與排查清單

檢查點命令/代碼期望值
資料庫字符集SHOW VARIABLES LIKE 'character_set_%';database/server/connection/results/client 全為 utf8mb4
表字符集SHOW CREATE TABLE t;CHARSET=utf8mb4
列字符集SHOW FULL COLUMNS FROM t;Collation: utf8mb4_unicode_ci
連接字符集SHOW VARIABLES LIKE 'character_set_connection';utf8mb4
JDBC 實際編碼conn.getMetaData().getDriverVersion() + 抓包分析發送字節為 UTF-8 編碼

常見坑位

  • utf8 ≠ utf8mb4: MySQL utf8 只支援 3 字節 (BMP),Emoji/生僻字需 utf8mb4 (4 字節)
  • 連接池缓存舊連接: 修改配置後需重啟應用/刷新連接池
  • MySQL 8.0 新認證: caching_sha2_password 需驅動 8.0.13+ 或建立用戶指定 mysql_native_password
  • 系統表仍為 latin1: mysql、information_schema 等系統庫不影響業務數據

最佳實踐總結

  1. 首選: 服務端 character-set-server=utf8mb4 + 連接 URL characterEncoding=utf8mb4 雙重保險
  2. 次選: 僅連接 URL 參數 (無服務器控制權時)
  3. 備選: 代碼手動轉碼 (極受限環境)
  4. 禁用: SET NAMES utf8 (SQL 注入風險、連接池失效)
  5. 統一: 應用、連接池、驅動、服務端、表、列全鏈路 utf8mb4
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved