java.sql.SQLException: Hatalı dize değeri: '\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F…'


107

Şu dize değerine sahibim: "walmart obama 👽💔"

MySQL ve Java kullanıyorum.

Şu istisnayı alıyorum: "java.sql.SQLException: Yanlış dize değeri: '\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F ...'

İşte eklemeye çalıştığım değişken:

var1 varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL`

"Walmart obama 👽💔" eklemeye çalışan Java kodum bir readyStatement. Bu yüzden setString()yöntemi kullanıyorum .

Görünüşe göre sorun, 👽💔 değerlerinin kodlanması. Bunu nasıl düzeltebilirim? Önceden Derby SQL kullanıyordum ve 👽💔 değerleri iki sqaures oldu (bence bu boş karakterin temsili)

Tüm yardımlar çok takdir edilmektedir!



Veritabanını oluşturduğunuzda, karakter setini ve harmanlamayı şu şekilde verebilirsiniz:CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Max Peng

Yanıtlar:


145

Sahip olduğunuz EXTRATERRESTRIAL ALIEN (U+1F47D)ve BROKEN HEART (U+1F494)temel çok dilli düzlemde olmayanlar. Java'da tek karakter olarak bile temsil edilemezler "👽💔".length() == 4. Kesinlikle boş karakterler değillerdir ve onları destekleyen yazı tiplerini kullanmıyorsanız kareler göreceksiniz.

MySQL utf8yalnızca temel çok dilli düzlemi destekler ve utf8mb4bunun yerine kullanmanız gerekir :

Ek bir karakter için utf8 karakteri hiç saklayamazken utf8mb4'ün saklaması için dört bayta ihtiyaç vardır. Utf8 karakteri hiç depolayamadığından, utf8 sütunlarında herhangi bir ek karakter yoktur ve MySQL'in eski sürümlerinden utf8 verilerini yükseltirken karakterleri dönüştürmek veya verileri kaybetmek konusunda endişelenmenize gerek yoktur.

Dolayısıyla bu karakterleri desteklemek için MySQL'inizin 5.5+ olması ve utf8mb4her yerde kullanmanız gerekir . Bağlantı kodlamasının olması utf8mb4, karakter setinin olması utf8mb4ve collaction olması gerekiyor utf8mb4. Java için hala adil "utf-8", ancak MySQL'in bir ayrıma ihtiyacı var.

Hangi sürücüyü kullandığınızı bilmiyorum, ancak bağlantı karakter kümesini ayarlamanın sürücüden bağımsız bir yolu sorguyu göndermektir:

SET NAMES 'utf8mb4'

Bağlantıyı yaptıktan hemen sonra.

Ayrıca Connector / J için buna bakın :

14.14: 4 baytlık UTF8, utf8mb4'ü Connector / J ile nasıl kullanabilirim?

4 baytlık UTF8'i Bağlayıcı / J ile kullanmak için MySQL sunucusunu character_set_server = utf8mb4 ile yapılandırın. Bağlayıcı / J sonra bu ayarı kullanacaktır uzun characterEncoding etti olduğunca değil bağlantı dizesinde seti olmuştur . Bu, karakter kümesinin otomatik olarak algılanmasına eşdeğerdir.

Sütunlarınızı ve veritabanınızı da ayarlayın:

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

Yine, MySQL sürümünüzün utf8mb4 desteği için nispeten güncel olması gerekir.


Diğer ilgili gönderime göz atın: stackoverflow.com/questions/13748170/… . Cevap verebilirseniz, bu soruyu da cevaplamış olursunuz. Diğer gönderide yaptığım şey hakkında daha fazla ayrıntı var.
CodeKingPlusPlus

1
@CodeKingPlusPlus, veritabanınızdaki her şeyi olarak değiştirdiniz utf8mb4mi, hala kullanıyormuşsunuz gibi görünüyor utf8_general_ci..
Esailija

1
Bağlayıcı / J ile "İSİMLERİ AYARLA" yapmayın: 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

2
Aynı sorunu yaşıyorum, yukarıdaki adımları izledim ancak C: \ ProgramData \ MySQL \ MySQL Server 5.7 \ my.ini
fattah.safa'da 2'16

16

Sonuç olarak, 4 bayt gerektiren sembolleri kaydetmek için, karakter kümesini ve harmanlamayı güncellemeniz gerekir utf8mb4:

  1. veritabanı tablosu / sütunu: alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
  2. veritabanı sunucusu bağlantısı ( bkz. )

# 2 için geliştirme ortamımda, sunucuyu başlatırken komut satırında parametreleri ayarlamayı tercih ediyorum: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci


btw, aşağıdaki durumlarda Bağlayıcı / J davranışına dikkat edin SET NAMES 'utf8mb4':

Sürücü karakter setinin değiştiğini algılamayacağından ve ilk bağlantı kurulumu sırasında algılanan karakter setini kullanmaya devam edeceğinden, Sorgu seti isimlerini Connector / J ile vermeyin.

Ve characterEncodingyapılandırılmış sunucu kodlamasını geçersiz kılacağından bağlantı url'sinde parametre ayarlamaktan kaçının :

İstemci tarafında otomatik olarak algılanan kodlamayı geçersiz kılmak için, sunucuya bağlanmak için kullanılan URL'deki characterEncoding özelliğini kullanın.


15

Tuhaftır, ben REMOVING bulundu &characterEncoding=UTF-8dan JDBC urlbenzer konularla benim için hile yaptı.

Mülklerime göre,

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

Sanırım bu, @Esailija'nın yukarıda söylediği şeyi destekliyor, yani gerçekten 5.5 olan MySQL, UTF-8 kodlamasının kendi favori lezzetini buluyor.

(Not, ayrıca java kodunda InputStreamolduğu gibi okuyorum UTF-8, muhtemelen zarar vermeyen) ...


Belki useUnicode=trueihtiyaç bile yok? Benim durumumda çalıştı tek şey kuruyor character_set_server=utf8mb4(RDS parametre grubu) sunucuda küresel ve DEĞİL JDBC URL içinde herhangi characterEncoding sahip.
Joshua Davis

6

Sorunumu nasıl çözdüm.

sahiptim

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

Hibernate jdbc bağlantı url'imde ve string veri tipini veritabanında daha önce varchar olan longtext olarak değiştirdim.


Bu sütunun dizine eklenmesine ve nispeten küçük olmasına ihtiyacınız yoksa harika, ancak bu numarayı tüm sütunlarım için yapabilirim
shareef

3

Satırı useUnicode=true&amp;characterEncoding=UTF-8jdbc url'nize ekleyin .

Sizin durumunuzda veriler UTF-8kodlama kullanılarak gönderilmiyor .


Bunu nasıl eklerim? Bağlantı dizemde mi? Yardımcı olacaksa Netbeans kullanıyorum.
CodeKingPlusPlus

Bağlantıyı nasıl oluşturuyorsunuz?
JHS

DriverManager.getConnection ("jdbc: mysql: // localhost: #### / [dbName]", [kullanıcı adı], [parola]);
CodeKingPlusPlus

Şöyle mi - DriverManager.getConnection ("jdbc: mysql: // localhost: #### / [dbName]? UseUnicode = true & amp; characterEncoding = UTF-8", [kullanıcı adı], [parola]);
JHS

1
Onu kaşı, '?' Ama şimdi orijinal
gönderiyle

3

Aynı sorunla karşılaştım ve Harmanlamayı her sütun için utf8_general_ci olarak ayarlayarak çözdüm .


2

Sanırım MySQL bunun geçerli UTF8 metni olduğuna inanmıyor. Aynı sütun tanımına sahip bir test tablosunda bir ekleme denedim (mysql istemci bağlantısı da UTF8 idi) ve eklemeyi yapmasına rağmen, MySQL CLI istemcisi ve JDBC ile aldığım veriler değerleri doğru şekilde almadı. UTF8'in doğru çalıştığından emin olmak için obama için "o" yerine "ö" ekledim:

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

Aşağıdakilerle test edilecek küçük java uygulaması:

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();
        }
    }

}

Çıktı:

johan@appel:~/workspaces/java/javatest/bin$ java test.sql.Test
test string=walmart öbama 👽💔
retrieved="walmart öbama "

Ayrıca, JDBC bağlantısıyla aynı eki denedim ve aldığınız istisnayı attı. Bunun bir MySQL hatası olduğuna inanıyorum. Belki zaten böyle bir durumla ilgili bir hata raporu vardır ..


Bu arada, dizenizdeki karakterler OSX'te hem Firefox'ta hem de Chrome'da doğru şekilde görünmüyor bile. İTerm uygulamamda doğru şekilde görünüyorlar. Bunun yazı tipine bağlı olduğunu düşünüyorum.
Cuma

1

Ben de aynı sorunu yaşadım ve tüm karakter kümelerine dikkatlice baktıktan ve iyi olduklarını anladıktan sonra, sınıfımdaki hatalı özelliğin @JoinColumn (javax.presistence; hazırda bekletme) yerine @Column olarak not edildiğini fark ettim ve her şeyi parçalıyordu.


1

yürütmek

show VARIABLES like "%char%”;

utf8mb4 değilse karakter kümesi sunucusunu bulun.

my.cnf dosyanızda ayarlayın

vim /etc/my.cnf

bir satır ekle

character_set_server = utf8mb4

mysql son yeniden başlatıldığında


1
character_set_serverseçenek DEĞİLcharacter-set-server
Arun SR

0

Bu ayar useOldUTF8Behavior = true benim için iyi çalıştı. Hatalı dizge hatası vermedi, ancak à gibi özel karakterleri birden çok karaktere dönüştürdü ve veritabanına kaydedildi.

Bu tür durumlardan kaçınmak için, bu özelliği JDBC parametresinden kaldırdım ve bunun yerine sütunumun veri türünü BLOB'a dönüştürdüm. Bu mükemmel çalıştı.


Cevabınıza daha fazla ayrıntı ekleyebilir misiniz? (kod, virgül vb.)
aBnormaLz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.