次の文字列値があります: "walmart obama ????????"
MySQLとJavaを使用しています。
次の例外が発生しています: `Java.sql.SQLException:Incorrect string value: '\ xF0\x9F\x91\xBD\xF0\x9F ...'
ここに私が挿入しようとしている変数があります:
var1 varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL`
「ウォルマートオバマ????????」を挿入しようとしている私のJavaコードpreparedStatementです。そこで、setString()
メソッドを使用しています。
問題は値のエンコーディングのようです????????。どうすれば修正できますか?以前は、Derby SQLと値を使用していました????????ちょうど2平方メートルになりました(これはヌル文字の表現だと思います)
すべてのヘルプは大歓迎です!
持っているのは EXTRATERRESTRIAL ALIEN (U+1F47D)
と BROKEN HEART (U+1F494)
で、これらは基本的な多言語面にはありません。 Javaでは、1つの文字"????????".length() == 4
として表現することさえできません。それらは間違いなくヌル文字ではなく、それらをサポートするフォントを使用していない場合は正方形が表示されます。
MySQLのutf8
は基本的な多言語プレーンのみをサポートし、代わりにutf8mb4
を使用する必要があります :
補助文字の場合、utf8はその文字をまったく格納できませんが、utf8mb4は格納に4バイトを必要とします。 utf8は文字をまったく格納できないため、utf8列に補助文字はなく、古いバージョンのMySQLからutf8データをアップグレードするときに文字の変換やデータの損失を心配する必要はありません。
したがって、これらの文字をサポートするには、MySQLが5.5以上であり、utf8mb4
をすべての場所で使用する必要があります。接続エンコードはutf8mb4
である必要があり、文字セットはutf8mb4
である必要があり、照合はutf8mb4
である必要があります。 Javaの場合、まだ"utf-8"
のままですが、MySQLには区別が必要です。
使用しているドライバーはわかりませんが、ドライバーに依存しない接続文字セットを設定する方法は、クエリを送信することです。
SET NAMES 'utf8mb4'
接続を確立した直後。
14.14:Connector/Jで4バイトUTF8、utf8mb4を使用するにはどうすればよいですか?
Connector/Jで4バイトUTF8を使用するには、character_set_server = utf8mb4でMySQLサーバーを設定します。 Connector/Jはその設定を使用しますcharacterEncodingがnotが接続文字列に設定されている限り。これは、文字セットの自動検出と同等です。
列とデータベースも調整します。
var1 varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
繰り返しますが、utf8mb4をサポートするには、MySQLのバージョンが比較的最新である必要があります。
全体として、4バイトを必要とするシンボルを保存するには、utf8mb4
の文字セットと照合を更新する必要があります。
alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
#2の開発環境では、サーバーの起動時にコマンドラインでパラメーターを設定することを好みます:mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ところで、 Connector/Jの動作 with SET NAMES 'utf8mb4'
に注意してください:
ドライバーは文字セットが変更されたことを検出せず、初期接続セットアップ中に検出された文字セットを引き続き使用するため、Connector/Jでクエリセット名を発行しないでください。
接続URLでcharacterEncoding
パラメーターを設定しないでください。設定されたサーバーエンコードがオーバーライドされるためです。
クライアント側で自動的に検出されたエンコードをオーバーライドするには、サーバーへの接続に使用されるURLでcharacterEncodingプロパティを使用します。
奇妙なことに、&characterEncoding=UTF-8
からJDBC url
を削除すると、同様の問題が発生することがわかりました。
私の特性に基づいて、
jdbc_url=jdbc:mysql://localhost:3306/dbName?useUnicode=true
これは@Esailijaが上記したことをサポートしていると思います。つまり、MySQL(実際には5.5)は、UTF-8エンコーディングの好みのフレーバーを見つけています。
(注:JavaコードでUTF-8
として読み取り中のInputStream
も指定しているため、おそらく問題はありません)...
問題をどのように解決したか。
持っていた
?useUnicode=true&characterEncoding=UTF-8
休止状態のjdbc接続URLで、データベースの文字列データ型をロングテキストに変更しました。これは以前はvarcharでした。
同じ問題に直面し、各列の照合をtf8_general_ciに設定することで解決しました。
MySQLはこれが有効なUTF8テキストであるとは考えていません。同じ列定義を持つテストテーブルで挿入を試みました(mysqlクライアント接続もUTF8でした)。挿入は行いましたが、MySQL CLIクライアントとJDBCで取得したデータは値を正しく取得しませんでした。 UTF8が正しく機能することを確認するために、オバマの「o」の代わりに「ö」を挿入しました。
johan@maiden:~$ mysql -vvv test < insert.sql
--------------
insert into utf8_test values(_utf8 "walmart öbama ????????")
--------------
Query OK, 1 row affected, 1 warning (0.12 sec)
johan@maiden:~$ file insert.sql
insert.sql: UTF-8 Unicode text
テスト対象の小さなJavaアプリケーション:
package test.sql;
import Java.sql.Connection;
import Java.sql.DriverManager;
import Java.sql.PreparedStatement;
import Java.sql.ResultSet;
public class Test
{
public static void main(String[] args)
{
System.out.println("test string=" + "walmart öbama ????????");
String url = "jdbc:mysql://hostname/test?useUnicode=true&characterEncoding=UTF-8";
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection c = DriverManager.getConnection(url, "username", "password");
PreparedStatement p = c.prepareStatement("select * from utf8_test");
p.execute();
ResultSet rs = p.getResultSet();
while (!rs.isLast())
{
rs.next();
String retrieved = rs.getString(1);
System.out.println("retrieved=\"" + retrieved + "\"");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
出力:
johan@appel:~/workspaces/Java/javatest/bin$ Java test.sql.Test
test string=walmart öbama ????????
retrieved="walmart öbama "
また、JDBC接続で同じ挿入を試みましたが、同じ例外がスローされました。これはMySQLのバグだと思います。たぶん、そのような状況についてのバグレポートがあるかもしれません。
行useUnicode=true&characterEncoding=UTF-8
をjdbcのURLに追加します。
あなたの場合、データはUTF-8
エンコーディングを使用して送信されていません。
私は同じ問題を抱えていたので、すべての文字セットを注意深く調べて、それらが正しいことを発見した後、クラスにあるバグのあるプロパティに@JoinColumn(javax.presistence; hibernate)ではなく@Columnの注釈が付けられていることに気付きましたそれはすべてを壊していました。
execute
show VARIABLES like "%char%”;
がutf8mb4でない場合、character-set-serverを見つけます。
次のようにmy.cnfに設定します
vim /etc/my.cnf
一行追加する
character_set_server = utf8mb4
最後にmysqlを再起動します
この設定useOldUTF8Behavior = trueは、私にとってはうまくいきました。不正な文字列エラーは発生しませんでしたが、Ãのような特殊文字を複数の文字に変換し、データベースに保存しました。
このような状況を回避するために、JDBCパラメーターからこのプロパティを削除し、代わりに列のデータ型をBLOBに変換しました。これは完璧に機能しました。