絵文字表現は日々の開発でよく遭遇しますが、最近mysqlに絵文字表現を挿入するときに問題に遭遇したので、関連情報を検索して最終的に解決したので、この記事は主にこの問題を解決するプロセスを共有します。 MySQL に絵文字表現を挿入できない問題の解決策を紹介しましたので、困っている人は参考にしてください。
はじめに
私は、最近この問題に遭遇するまで、UTF-8 が文字セットの問題に対する普遍的な解決策であると考えていました。最近、Sina Weibo のクローラーを作成していて、保存するときに絵文字表現を保持している限り、次の例外がスローされることがわかりました:
Incorrect string value: '\xF0\x90\x8D\x83\xF0\x90...'
ご存知のとおり、UTF-8 は3 バイトには、私がこれまでに見たフォントのほとんどが含まれていますが、すべてのテキストを収容するには十分ではないため、utf8mb4 は utf8 のスーパーセットで、4 バイトを占めます。 utf8 と互換性があります。私たちが毎日使用する絵文字です。絵文字はわずか 4 バイトです。
そのため、utf8 データ テーブルにデータを挿入すると、エラー Incorrect string value
が報告されます。Incorrect string value
这个错误.
Google一下很容易就找到了解决方案, 具体解决办法是如下:
一、修改数据表的字符集为utf8mb4
这点很简单, 修改语句网上找一大堆, 不过建议重新建表, 使用 mysqldump -uusername -ppassword database_name table_name > table.sql
备份相应数据表, 并修改其中的建表语句的字符集为 utf8mb4 即可, 然后 mysql -uusername -ppassword database_name < table.sql
重新导入sql即可完成修改字符集操作.
二、MySQL数据库版本要5.5.3及以上
网络上所有的文章都说明要MySQL 5.5.3以上的版本才支持utf8mb4, 不过我使用的数据库版本为5.5.18, 最终仍能解决问题, 所以同学们不要急着找运维哥哥升级数据库先, 先试试能不能自己解决问题.
三、修改数据库配置文件/etc/my.cnf并重启mysql服务
主要是修改数据库的默认字符集, 以及连接, 查询的字符集, [Mysql支持emoji 表情符号 升级编码为UTF8MB4][1] 这篇文章有详细的设置方法, [深入Mysql字符集设置][2] 这篇文章有其中设置的各个字符集的作用, 大家可以科普下.
四、升级MySQL Connector到5.1.21及以上
以上所有的操作, 最关键的是步骤3, 修改数据库的配置文件, 其中大概修改了
[client] # 客户端来源数据的默认字符集 default-character-set = utf8mb4 [mysqld] # 服务端默认字符集 character-set-server=utf8mb4 # 连接层默认字符集 collation-server=utf8mb4_unicode_ci [mysql] # 数据库默认字符集 default-character-set = utf8mb4
这些配置指定了数据从客户端到服务端所经过的一条条管道使用的字符集, 其中每一个管道出现问题都可能会导致插入失败或者乱码.
但很多时候, 线上的数据库是不能随便修改数据库文件的, 所以我们的运维同学很果断的回绝了我修改数据库配置文件的请求(T_T)
所以就只能用代码解决了, 一开始是准备从JDBC连接时候就指定使用的字符集处下手.
jdbc:mysql://localhost:3306/ding?characterEncoding=UTF-8
主要把UTF-8修改为utf8mb4对于的Java Style Charset字符串应该就能解决问题吧?
不过很遗憾的是, Java JDBC并不存在utf8mb4对于的字符集. 使用UTF-8的时候可以兼容urf8mb4并自动转换字符集.
For example, to use 4-byte UTF-8 character sets with Connector/J, configure the MySQL server with character_set_server=utf8mb4, and leave characterEncoding out of the Connector/J connection string. Connector/J will then autodetect the UTF-8 setting. – [MySQL:Using Character Sets and Unicode][3]
后来科普了一下, 在每一次查询请求的时候, 可以显式的指定使用的字符集, 使用 set names utf8mb4
可以指定本次链接的字符集为utf8mb4, 但这个设置在每次连接被释放后都会失效.
目前的解决办法是, 在需要插入utf8mb4的时候, 显示地调用执行set names utf8mb4
, 如:
jdbcTemplate.execute("set names utf8mb4"); jdbcTempalte.execute("...");
需要注意的是, 我们在使用一下ORM框架的时候, 因为性能优化原因, 框架会延迟提交, 除非事务结束或者用户主动调用强制提交, 负责执行的set names utf8mb4
1. データテーブルの文字セットをutf8mb4に変更します
これは非常に簡単な変更文がたくさん見つかります。オンラインですが、テーブルを再構築して mysqldump -uusername -ppassword database_name table_name > table.sql
を使用することをお勧めします。 対応するデータ テーブルをバックアップし、テーブル作成ステートメントの文字セットを utf8mb4 に変更します。次に、 mysql -uusername -ppassword database_name < table .sql
SQL を再インポートして、文字セットの変更操作を完了します
2. MySQL データベースのバージョンは 5.5.3 以降である必要があります。
// MessageDao public interface MessageDao { @Update("set names utf8mb4") public void setCharsetToUtf8mb4(); @Insert("insert into tb_message ......") public void insert(Message msg); } // test code SqlSession sqlSession = sqlSessioFactory.openSession(); messageDao = sqlSession.getMapper(MessageDao.class); messageDao.setCharsetToUtf8mb4(); // 强制提交 sqlSession.commit(); messageDao.insert(message);
set names utf8mb4
を使用します。 utf8mb4 と同じですが、この設定は接続が解放されるたびに無効になります 🎜🎜🎜 現在の解決策は、utf8mb4 を挿入するときに、次のように set names utf8mb4
を明示的に呼び出して実行することです。 🎜rrreee🎜 ORM フレームワークを使用する場合、パフォーマンス最適化の理由により、トランザクションが終了するかユーザーが積極的に強制コミットを呼び出しない限り、フレームワークは遅延コミットすることに注意してください。set names utf8mb4
実行責任はまだ有効になりません🎜🎜🎜ここでは、MessageDao を例として myBatis を使用しています🎜🎜🎜🎜 🎜rrreee🎜この時点で、問題は解決されています...🎜🎜🎜プロジェクトでは、mybatis インスタンスが Spring によって管理されているため、sqlSession を取得できず、Spring トランザクション フレームワークの制限により強制的に送信することもできません。ユーザーが明示的に強制送信を呼び出すことを許可しない 🎜🎜🎜🎜 解決策は 2 つあります。AOP を使用すると、4 バイトの UTF8 文字を挿入できる場合、prefix メソッドは set names utf8mb4
を実行しますが、このソリューションは AOP メソッドが Spring によって管理されるかどうかはまだわかりません。フロントエンドメソッドでは、取得したリンクが次に取得した接続オブジェクトと同じセッションかどうかを確認しますset names utf8mb4
, 但该方案还不能确定AOP的方法会被Spring进行事务管理么, 并且在前置方法中,拿到的链接是否和接下来拿到的连接对象是同一个session.
研究Spring JDBC的创建方法, 写一个hook在每次创建新的数据库连接的时候, 都执行一次set names utf8mb4
以上がMySQL への絵文字表現の挿入に失敗する問題の解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。