116

次の文字列値があります: "ウォルマート オバマ"

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 つの正方形になってしまいました (これは null 文字の表現だと思います)。

すべてのヘルプは大歓迎です!

4

11 に答える 11

152

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

MySQLは基本多言語面のみをサポートしており、代わりにutf8utf8mb4を使用する必要があります。

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

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

使用しているドライバーはわかりませんが、ドライバーに依存しない接続文字セットを設定する方法は、クエリを送信することです。

SET NAMES 'utf8mb4'

接続した直後。

Connector / Jについては、これも参照してください

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

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

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

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

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

于 2012-12-07T00:15:18.547 に答える
17

全体として、4 バイトを必要とするシンボルを保存するには、characher-set と collat​​ion for を更新する必要があります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 プロパティを使用します。

于 2015-12-22T18:40:54.430 に答える
3

useUnicode=true&amp;characterEncoding=UTF-8をjdbcURLに追加します。

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

于 2012-11-30T21:54:31.987 に答える
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 のバグだと思います。たぶん、そのような状況に関するバグレポートがすでにあります..

于 2012-12-06T12:34:58.120 に答える