5

我正在使用 Netbeans 构建一个使用 Java、JSP 处理带有希伯来字段的数据库的 Web 应用程序。

DDL 如下:

String cityTable = "CREATE TABLE IF NOT EXISTS hebrew_test.table ("
                            +"id int(11) NOT NULL AUTO_INCREMENT,"
                            +"en varchar(30) NOT NULL,"
                            +"he varchar(30) COLLATE utf8_bin NOT NULL,"
                            +"PRIMARY KEY (id)"
                            +") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1;";
String insert = "INSERT INTO hebrew_test.table (en, he) VALUES ('A','a')";
String insert2 = "INSERT INTO hebrew_test.table (en, he) VALUES ('B','ב')";
String insert3 = "INSERT INTO hebrew_test.table (en, he) VALUES ('C','אבג')";


executeSQLCommand(cityTable);
executeSQLCommand(insert);
executeSQLCommand(insert2);
executeSQLCommand(insert3);

我得到的输出表:

1   A   a
2   B   ?
3   C   ???

代替:

1   A   a
2   B   ב
3   C   אבג

我试过希伯来语在 Netbeans 中显示为问号,但这不是同一个问题。我得到了表中的问号。

UTF8_bin正如您在上面的代码中看到的那样,我还定义了要在其中的表。

4

2 回答 2

7

您需要告诉 JDBC 驱动程序在将表示 SQL 查询的字符解码为字节时使用 UTF-8 编码。您可以通过向JDBC 连接 URL添加useUnicode=yes和查询参数来做到这一点。characterEncoding=UTF-8

jdbc:mysql://localhost:3306/db_name?useUnicode=yes&characterEncoding=UTF-8

否则它将使用操作系统平台默认字符集。MySQL JDBC 驱动程序本身非常了解客户端(JDBC 代码运行的地方)和服务器端(DB 表所在的地方)使用的编码。数据库表使用的字符集未涵盖的任何字符都将替换为问号。

也可以看看:

于 2013-01-02T02:37:40.707 回答
2

您将值直接包含在 SQL 中。这总是一个坏主意。使用PreparedStatement参数化 SQL,并将值设置为参数。它可能无法解决问题——但这绝对是首先要尝试的事情,因为无论如何您都应该使用参数化 SQL。(参数化 SQL 避免了SQL 注入攻击,将代码与数据分离,避免了不必要的转换。)

接下来,您应该准确找出问题真正发生的位置:

  • 确保您尝试插入的值是正确的。
  • 检查您检索的值是否正确。
  • 使用Wireshark检查您的网络响应中的内容- 检查声明的编码实际数据中的内容

检查值时,您应该遍历字符串中的每个字符并将值打印为 UTF-16 代码单元(使用toCharArray()charAt()在循环中使用)。只是将值打印到控制台会留下太多其他问题的机会。

编辑:关于我为什么写这个作为答案的一点背景:

  • 根据我的经验,将字符串值作为参数而不是直接包含在 SQL 中有时可以避免此类问题(出于安全原因等原因当然更好)。
  • 根据我的经验,诊断问题出在数据库端还是 Web 端也很重要。最好通过记录所使用的确切 UTF-16 代码单元来完成此诊断,而不仅仅是字符串(否则在记录或控制台输出期间可能会出现进一步的编码问题)。
  • 以我的经验,这样的问题很容易在插入读取代码路径中发生。

作为推动 OP 前进的一种方式,所有这些都很重要,而不仅仅是在类似评论的请求中获取更多信息。

于 2013-01-01T18:18:38.437 回答