java.sql.SQLException: valor de cadena incorrecto: ‘\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F …’

Tengo el siguiente valor de cadena: “walmart obama 👽💔”

Estoy usando MySQL y Java.

Recibo la siguiente excepción: `java.sql.SQLException: valor de cadena incorrecto: ‘\ xF0 \ x9F \ x91 \ xBD \ xF0 \ x9F …’

Aquí está la variable que estoy tratando de insertar:

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

Mi código de Java que está tratando de insertar “walmart obama 👽💔” es una statement preparada. Entonces estoy usando el método setString() .

Parece que el problema es la encoding de los valores 👽💔. ¿Cómo puedo arreglar esto? Anteriormente estaba usando Derby SQL y los valores 👽💔 simplemente terminaron siendo dos cuadrados (creo que esta es la representación del carácter nulo)

¡Toda ayuda es muy apreciada!

    Lo que tiene es EXTRATERRESTRIAL ALIEN (U+1F47D) y BROKEN HEART (U+1F494) que no están en el plano multilingüe básico. No pueden ser representados en Java como un char, "👽💔".length() == 4 . Definitivamente no son caracteres nulos y uno verá cuadrados si no está usando fonts que los admitan.

    El utf8 de MySQL solo es compatible con el plano multilingüe básico, y necesita usar utf8mb4 en utf8mb4 lugar :

    Para un carácter suplementario, utf8 no puede almacenar el carácter en absoluto, mientras que utf8mb4 requiere cuatro bytes para almacenarlo. Como utf8 no puede almacenar el carácter en absoluto, no tiene ningún carácter adicional en las columnas utf8 y no necesita preocuparse por la conversión de caracteres o la pérdida de datos al actualizar datos utf8 de versiones anteriores de MySQL.

    Para admitir estos caracteres, su MySQL necesita ser 5.5+ y necesita usar utf8mb4 todas partes. La encoding de la conexión debe ser utf8mb4 , el juego de caracteres debe ser utf8mb4 y la combinación debe ser utf8mb4 . Para Java, sigue siendo solo "utf-8" , pero MySQL necesita una distinción.

    No sé qué controlador está usando, pero una forma independiente del controlador para establecer el juego de caracteres de conexión es enviar la consulta:

     SET NAMES 'utf8mb4' 

    Justo después de hacer la conexión.

    Ver también esto para Connector / J :

    14.14: ¿Cómo puedo usar 4-byte UTF8, utf8mb4 con Connector / J?

    Para usar UTF8 de 4 bytes con Connector / J, configure el servidor MySQL con character_set_server = utf8mb4. Connector / J usará esa configuración siempre que no se haya establecido characterEncoding en la cadena de conexión . Esto es equivalente a la autodetección del juego de caracteres.

    Ajuste sus columnas y base de datos también:

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

    De nuevo, su versión de MySQL necesita estar relativamente actualizada para el soporte de utf8mb4.

    En general, para guardar símbolos que requieren 4 bytes, necesita actualizar el conjunto de caracteres y la intercalación para utf8mb4 :

    1. tabla / columna de la base de datos: alter table convert to character set utf8mb4 collate utf8mb4_unicode_ci
    2. conexión del servidor de base de datos ( ver )

    En mi entorno de desarrollo para el n. ° 2, prefiero establecer parámetros en la línea de comando al iniciar el servidor: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci


    Por cierto, preste atención al comportamiento del conector / J con SET NAMES 'utf8mb4' :

    No emita los nombres de conjunto de consulta con Connector / J, ya que el controlador no detectará que el juego de caracteres ha cambiado y continuará utilizando el conjunto de caracteres detectado durante la configuración de la conexión inicial.

    Y evite establecer el parámetro characterEncoding en la url de conexión ya que anulará la encoding configurada del servidor:

    Para anular la encoding detectada automáticamente en el lado del cliente, use la propiedad characterEncoding en la URL utilizada para conectarse al servidor.

    Extrañamente, encontré que REMOVING &characterEncoding=UTF-8 de la JDBC url sirvió de algo similar con problemas similares.

    Basado en mis propiedades,

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

    Creo que esto respalda lo que dijo @Esailija anteriormente, es decir, mi MySQL, que de hecho es 5.5, está descifrando su propio sabor favorito de la encoding UTF-8.

    (Nota, también estoy especificando el InputStream que estoy leyendo como UTF-8 en el código de Java, que probablemente no duela) …

    Cómo resolví mi problema.

    tuve

     ?useUnicode=true&characterEncoding=UTF-8 

    En mi url de conexión jdbc de hibernación y cambié el tipo de datos de cadena a longtext en la base de datos, que antes era varchar.

    Enfrenté el mismo problema y lo resolví estableciendo la intercalación en utf8_general_ci para cada columna.

    useUnicode=true&characterEncoding=UTF-8 la línea useUnicode=true&characterEncoding=UTF-8 a su URL jdbc.

    En su caso, los datos no se envían utilizando la UTF-8 .

    Supongo que MySQL no cree que este sea un texto UTF8 válido. Probé una inserción en una tabla de prueba con la misma definición de columna (la conexión del cliente mysql también era UTF8) y aunque lo hizo, los datos que obtuve con el cliente CLI de MySQL y JDBC no recuperaron los valores correctamente. Para estar seguro de que UTF8 funcionó correctamente, inserté un “ö” en lugar de una “o” para obama:

     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 

    Pequeña aplicación Java para probar con:

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

    Salida:

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

    Además, probé la misma inserción con la conexión JDBC y arrojó la misma excepción que está recibiendo. Creo que esto es un error de MySQL. Quizás ya haya un informe de error sobre tal situación ...

    Tuve el mismo problema y después de ir cuidadosamente contra todos los conjuntos de caracteres y descubrir que estaban bien, me di cuenta de que la propiedad con errores que tenía en mi clase estaba anotada como @Column en lugar de @JoinColumn (javax.presistence; hibernate) y estaba rompiendo todo.

    ejecutar

     show VARIABLES like "%char%”; 

    encuentra character-set-server si no es utf8mb4.

    configúralo en tu my.cnf, como

     vim /etc/my.cnf 

    agregar una línea

     character-set-server = utf8mb4 

    en el último reinicio mysql