java.sql.SQLException:不正な文字列値: '\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F…'


107

次の文字列値があります: "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()メソッドを使用しています。

問題は値のエンコードですis。どうすれば修正できますか?以前はDerby SQLを使用していて、値👽💔が2平方フィートになった(これはnull文字の表現だと思う)

すべての助けに大歓迎です!



:データベースを作成するときには、このようなキャラクタセットと照合与えることができますCREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
最大鵬

回答:


145

あなたが持っていることであるEXTRATERRESTRIAL ALIEN (U+1F47D)BROKEN HEART (U+1F494)され、基本多言語面ではありません。Javaでは1つの文字として表現することもできません"👽💔".length() == 4。それらは間違いなくnull文字ではなく、それらをサポートするフォントを使用していない場合は正方形が表示されます。

MySQL utf8は基本的な多言語プレーンのみをサポートしており、utf8mb4代わりに使用する必要があります

補助文字の場合、utf8は文字をまったく格納できませんが、utf8mb4は文字を格納するために4バイトを必要とします。utf8は文字をまったく格納できないため、utf8列に補助文字がなく、古いバージョンのMySQLからutf8データをアップグレードするときに文字の変換やデータの損失について心配する必要はありません。

したがって、これらの文字をサポートするには、MySQLが5.5以降であり、utf8mb4あらゆる場所で使用する必要があります。接続エンコーディングutf8mb4、文字セット、utf8mb4およびcollactionである必要がありますutf8mb4。Javaの場合はまだです"utf-8"が、MySQLには区別が必要です。

私はあなたが使用しているドライバーを知りませんが、接続文字セットを設定するドライバーにとらわれない方法はクエリを送信することです:

SET NAMES 'utf8mb4'

接続した直後。

Connector / Jについては、こちらもご覧ください

14.14:4バイトUTF8、utf8mb4をConnector / Jで使用するにはどうすればよいですか?

Connector / Jで4バイトUTF8を使用するには、MySQLサーバーをcharacter_set_server = utf8mb4で構成します。Connector / Jは、characterEncodingが接続文字列で設定されていない限り、その設定使用し ます。これは、文字セットの自動検出と同等です。

列とデータベースも調整します。

var1 varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL

繰り返しますが、MySQLのバージョンはutf8mb4サポートのために比較的最新である必要があります。


私の他の関連する投稿を確認してください:stackoverflow.com/questions/13748170/…。あなたがそれに答えることができるなら、あなたはこの質問にも答えているでしょう。もう1つの投稿には、私が行ったことの詳細があります。
CodeKingPlusPlus

1
@CodeKingPlusPlusは、あなたがあなたのデータベースにすべてを変えていutf8mb4ますが、まだ使用されているように見える、utf8_general_ci...
Esailija

1
コネクタ/ Jと「セット名」をしないでください。dev.mysql.com/doc/connector-j/en/... Do not issue the query set names with Connector/J, as the driver will not detect that the character set has changed, and will continue to use the character set detected during the initial connection setup.
bcoughlan

1
:ケースで、あなただけの代わりに、あなたのDBを変更するの混乱に対処するためのBMP外の文字から取り除く、こちらを見てみたいstackoverflow.com/questions/4035562/...
Indigenuity

2
私は同じ問題を抱えており、上記の手順に従いましたが、C:\ ProgramData \ MySQL \ MySQL Server 5.7 \ my.iniのcharacter-set-server = utf8mb4を変更するまで解決されませんでした
fattah.safa

16

全体として、4バイトを必要とするシンボルを保存するには、次の文字セットと照合を更新する必要がありますutf8mb4

  1. データベーステーブル/列: alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
  2. データベースサーバー接続(を参照

#2の開発環境では、サーバーの起動時にコマンドラインでパラメーターを設定することを好みます。 mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci


ところで、Connector / Jの動作に注意してSET NAMES 'utf8mb4'ください:

ドライバーは文字セットが変更されたことを検出せず、初期接続セットアップ中に検出された文字セットを引き続き使用するため、Connector / Jでクエリセット名を発行しないでください。

また、characterEncoding構成されたサーバーのエンコーディングを上書きするため、接続URLにパラメーターを設定しないでください。

クライアント側で自動的に検出されたエンコーディングをオーバーライドするには、サーバーへの接続に使用されるURLでcharacterEncodingプロパティを使用します。


15

変なふうに、私は取り外しことがわかった&characterEncoding=UTF-8から、JDBC url同様の問題を私のためのトリックを行いました。

私の特性に基づいて、

jdbc_url=jdbc:mysql://localhost:3306/dbName?useUnicode=true

これは、@ Esailijaが上で言ったことをサポートしていると思います。つまり、MySQL(実際には5.5)は、独自の好みのUTF-8エンコーディングを理解しています。

(注意:JavaコードのInputStreamようUTF-8に、私が読み込んでいるものも指定していますが、おそらく害はありません)...


多分useUnicode=true必要ないのでしょうか?私の場合で働いていた唯一のものは、設定されたcharacter_set_server=utf8mb4(RDSパラメータグループ)のサーバー上でグローバルとしない JDBC URL内の任意characterEncodingを持ちます。
ジョシュアデイビス

6

私の問題をどのように解決したか。

持っていた

?useUnicode=true&amp;characterEncoding=UTF-8

hibernate jdbc接続URLで、データベースの文字列データ型をロングテキストに変更しました。以前はvarcharでした。


その列にインデックスを付ける必要がなく、その列が比較的小さい場合に
最適

3

この行useUnicode=true&amp;characterEncoding=UTF-8をjdbcのURLに追加します。

あなたの場合、データはUTF-8エンコーディングを使用して送信されていません。


これをどのように追加しますか?私の接続文字列では?それが役立つ場合は、Netbeansを使用しています。
CodeKingPlusPlus

接続をどのように作成していますか?
JHS、2012年

DriverManager.getConnection( "jdbc:mysql:// localhost:#### / [dbName]"、[ユーザー名]、[パスワード]);
CodeKingPlusPlus

次のようにします-DriverManager.getConnection( "jdbc:mysql:// localhost:#### / [dbName]?useUnicode = true&amp; characterEncoding = UTF-8"、[ユーザー名]、[パスワード]);
JHS、2012年

1
スクラッチ、私は「?」を忘れました しかし、今は元の投稿と同じエラーに戻っています...
CodeKingPlusPlus

3

同じ問題に直面し、各列の照合順序utf8_general_ciに設定することで解決しました。


2

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のバグだと思います。たぶん、そのような状況に関するバグレポートはすでにあるでしょう。


ちなみに、文字列の文字は、FirefoxとOSX上のChromeの両方で正しく表示されません。それらは私のiTermアプリケーションで正しく表示されます。これはフォントに依存すると思います。
フリーク

1

私は同じ問題を抱えていて、すべての文字セットを注意深く調べて問題がないことを確認した後、クラスにあるバグのあるプロパティに@JoinColumn(javax.presistence; hibernate)ではなく@Columnと注釈が付けられていることに気付きましたそれはすべてを壊していました。


1

実行する

show VARIABLES like "%char%”;

utf8mb4でない場合は、文字セットサーバーを検索します。

my.cnfに次のように設定します

vim /etc/my.cnf

1行追加する

character_set_server = utf8mb4

最後にmysqlを再起動します


1
character_set_serverオプション、NOTがあるcharacter-set-server
アルンSR

0

この設定useOldUTF8Behavior = trueは私にとってはうまくいきました。不正な文字列エラーは発生しませんでしたが、likeなどの特殊文字が複数の文字に変換され、データベースに保存されました。

このような状況を回避するために、JDBCパラメーターからこのプロパティを削除し、代わりに列のデータ型をBLOBに変換しました。これは完璧に機能しました。


あなたの答えにもっと詳細を追加していただけませんか?(コード、カンマントなど)
aBnormaLz

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.