java.sql.SQLException: valor de cadena incorrecto: ''/ xF0 / x9F / x91 / xBD / xF0 / x9F...''
mysql encoding (8)
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.
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 declaración preparada. Entonces estoy usando el método setString()
.
Parece que el problema es la codificación 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!
En general, para guardar símbolos que requieren 4 bytes, necesita actualizar el conjunto de caracteres y la intercalación para utf8mb4
:
- tabla / columna de la base de datos:
alter table <some_table> convert to character set utf8mb4 collate utf8mb4_unicode_ci
- conexión del servidor de base de datos ( see )
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 dev.mysql.com/doc/connector-j/en/… 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 codificación configurada del servidor:
Para anular la codificación 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 codificación 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) ...
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 fuentes que los admitan.
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 codificación 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.
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.
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
.
Enfrenté el mismo problema y lo resolví estableciendo la intercalación en utf8_general_ci para cada columna.