問題
通過 jdbc 向數據庫中插入數據時,由於字段值有 emoji。導致錯誤:
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\xA0\xBB\xB8\xE5\x90...' for column 'address' at row 1
-
環境
庫本身的字符集設置爲 utf8。
但是 character_set_client,character_set_connection,character_set_results 均爲 utf8mb4。
utf8mb4 是 utf8 的超集(參考:https://blog.csdn.net/vsiryxm/article/details/82919643)
MySQL [(none)]> show variables like 'character%';
+--------------------------+---------------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /u01/mysql57_20190925/share/charsets/ |
+--------------------------+---------------------------------------+
建表語句
CREATE TABLE `detail` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`address` varchar(100) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '地址',
) ENGINE=InnoDB AUTO_INCREMENT=6162 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
可見:
- 表本身編碼爲 utf8mb4,是支持寫入 emoji 的。
- character_set_client,character_set_connection,character_set_results 均爲 utf8mb4。這說明客戶端只要正常連上,不做任何字符集設置修改,就能夠寫入 emoji。
排查
- 問題出在客戶端 jdbc 配置上。
查看 jdbc 的連接串:
connectTimeout=3000;autoReconnect=true;failOverReadOnly=false;socketTimeout=900000;rewriteBatchedStatements=true;characterEncoding=utf8
可以看到 characterEncoding=utf8 的設置。
參看 mysql 官方文檔(https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html)
characterEncoding: If 'useUnicode' is set to true, what character encoding should the driver use when dealing with strings?
而 useUnicode 默認爲 true。
可見:正是 characterEncoding=utf8 這個設置導致了 emoji 無法正確插入。
解決
1. 連接串的 characterEncoding=utf8 改成 characterEncoding=utf8mb4
或者
2. 添加 connectionInitSql 參數
connectTimeout=3000;autoReconnect=true;failOverReadOnly=false;socketTimeout=900000;rewriteBatchedStatements=true;characterEncoding=utf8;connectionInitSql=set names utf8mb4
延伸閱讀
- mysql jdbc 連接串中所有參數
https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html
- utf8 與 utf8mb4 區別
https://blog.csdn.net/vsiryxm/article/details/82919643
utf8mb4 是 utf8 的超集,除了將編碼改爲utf8mb4外,不需要做其他轉換。
- mysql 的 set names 做了什麼?
https://blog.csdn.net/justsomebody126/article/details/103728644