Hibernate 應用向 MySQL 寫入中文出現亂碼,是經典的「兩頭 UTF-8、中間不通」問題。本質上不限於 Hibernate,任何 JDBC 連接(含 PHP PDO、Python、Go 等)若連接字串未顯式指定字符編碼,驅動程式會採用預設編碼(通常是 Latin1),導致中文在傳輸層錯誤編碼/解碼。本文提供標準解決方案:JDBC URL 參數 useUnicode=true&characterEncoding=utf8 及 XML 配置中的 CDATA 包裹技巧。
System.out.println 顯示中文正常??? 或 鏉ユ簮)定位:連接層編碼未指定,驅動預設 Latin1 處理中文位元組流。
<property name="connection.url">
jdbc:mysql://localhost:3306/tablename
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/tablename?useUnicode=true&characterEncoding=utf8
</property>
關鍵參數:
useUnicode=true:啟用 Unicode 支援characterEncoding=utf8:指定傳輸層編碼為 UTF-8(MySQL 的 utf8 即 utf8mb3,8.0+ 建議 utf8mb4)在 XML 中 & 是實體引用起始符,直接寫 &characterEncoding 會被解析器誤判。兩種修正:
<property name="connection.url">
jdbc:mysql://localhost:3306/tablename?useUnicode=true&characterEncoding=utf8
</property>
<property name="connection.url">
<![CDATA[
jdbc:mysql://localhost:3306/tablename?useUnicode=true&characterEncoding=utf8
]]>
</property>
CDATA 內容不被 XML 解析器處理,原樣輸出,適合含特殊字元的 URL。
jdbc:mysql://localhost:3306/your_db?
useUnicode=true&
characterEncoding=utf8mb4&
serverTimezone=Asia/Taipei&
useSSL=false&
allowPublicKeyRetrieval=true&
autoReconnect=true&
failOverReadOnly=false&
maxReconnects=3
關鍵新增參數:
characterEncoding=utf8mb4:支援 Emoji/生僻字(需資料表也為 utf8mb4)serverTimezone=Asia/Taipei:避免時區解析警告/錯誤useSSL=false:開發環境關閉 SSL(生產建議開啟並配置憑證)allowPublicKeyRetrieval=true:配合 caching_sha2_password 插件-- 資料庫預設字符集
ALTER DATABASE `your_db` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
-- 資料表預設字符集
ALTER TABLE `your_table` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
-- 修改現有欄位字符集
ALTER TABLE `your_table` MODIFY `col_name` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 檢查當前設置
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
SELECT HEX(col_name), col_name FROM table;| 現象 | 可能原因 | 解決 |
|---|---|---|
| 仍有亂碼 | 資料表/欄位字符集非 utf8mb4 | 執行 ALTER TABLE 轉換 |
| Emoji 存成 ???? | 字符集為 utf8 (utf8mb3) 非 utf8mb4 | 全鏈路升級 utf8mb4 |
| 讀取正常、寫入亂碼 | 僅配置了讀取端編碼 | 確認 JDBC URL 含 characterEncoding |
| XML 解析錯誤 | URL 中 & 未轉義或 CDATA 格式錯誤 | 用 & 或 CDATA 包裹 |
Hibernate/MySQL 中文亂碼 99% 是JDBC 連接字串缺少 useUnicode=true&characterEncoding=utf8(mb4)。修正 XML 配置(注意 & 或 CDATA)、同步資料庫/資料表/欄位字符集為 utf8mb4、驗證全鏈路編碼一致,即可徹底解決。此原理適用於所有 JDBC 應用,不限於 Hibernate。